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_identity_service.h"
32 #include "gnunet_namestore_service.h"
33 #include "gnunet_protocols.h"
34 #include "gnunet_reclaim_attribute_lib.h"
35 #include "gnunet_reclaim_service.h"
36 #include "gnunet_signatures.h"
45 * Normal operation state
47 #define STATE_POST_INIT 1
50 * Minimum interval between updates
52 #define MIN_WAIT_TIME GNUNET_TIME_UNIT_MINUTES
58 static struct GNUNET_IDENTITY_Handle *identity_handle;
63 static struct GNUNET_NAMESTORE_Handle *nsh;
68 static struct GNUNET_SCHEDULER_Task *timeout_task;
73 static struct GNUNET_SCHEDULER_Task *update_task;
78 static const struct GNUNET_CONFIGURATION_Handle *cfg;
86 * A ticket iteration operation.
88 struct TicketIteration
93 struct TicketIteration *next;
98 struct TicketIteration *prev;
101 * Client which intiated this zone iteration
103 struct IdpClient *client;
106 * The operation id fot the iteration in the response for the client
111 * The ticket iterator
113 struct RECLAIM_TICKETS_Iterator *iter;
118 * An attribute iteration operation.
120 struct AttributeIterator
123 * Next element in the DLL
125 struct AttributeIterator *next;
128 * Previous element in the DLL
130 struct AttributeIterator *prev;
133 * IDP client which intiated this zone iteration
135 struct IdpClient *client;
138 * Key of the zone we are iterating over.
140 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
145 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
148 * The operation id fot the zone iteration in the response for the client
162 struct IdpClient *prev;
167 struct IdpClient *next;
172 struct GNUNET_SERVICE_Client *client;
175 * Message queue for transmission to @e client
177 struct GNUNET_MQ_Handle *mq;
181 * Attribute iteration operations in
182 * progress initiated by this client
184 struct AttributeIterator *attr_iter_head;
188 * Attribute iteration operations
189 * in progress initiated by this client
191 struct AttributeIterator *attr_iter_tail;
194 * Head of DLL of ticket iteration ops
196 struct TicketIteration *ticket_iter_head;
199 * Tail of DLL of ticket iteration ops
201 struct TicketIteration *ticket_iter_tail;
204 * Head of DLL of ticket revocation ops
206 struct TicketRevocationOperation *revoke_op_head;
209 * Tail of DLL of ticket revocation ops
211 struct TicketRevocationOperation *revoke_op_tail;
214 * Head of DLL of ticket issue ops
216 struct TicketIssueOperation *issue_op_head;
219 * Tail of DLL of ticket issue ops
221 struct TicketIssueOperation *issue_op_tail;
224 * Head of DLL of ticket consume ops
226 struct ConsumeTicketOperation *consume_op_head;
229 * Tail of DLL of ticket consume ops
231 struct ConsumeTicketOperation *consume_op_tail;
234 * Head of DLL of attribute store ops
236 struct AttributeStoreHandle *store_op_head;
239 * Tail of DLL of attribute store ops
241 struct AttributeStoreHandle *store_op_tail;
243 * Head of DLL of attribute delete ops
245 struct AttributeDeleteHandle *delete_op_head;
248 * Tail of DLL of attribute delete ops
250 struct AttributeDeleteHandle *delete_op_tail;
255 * Handle for attribute deletion request
257 struct AttributeDeleteHandle
262 struct AttributeDeleteHandle *next;
267 struct AttributeDeleteHandle *prev;
272 struct IdpClient *client;
277 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
283 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
288 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
291 * The attribute to delete
293 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
298 struct TicketRecordsEntry *tickets_to_update_head;
303 struct TicketRecordsEntry *tickets_to_update_tail;
318 * Handle for attribute store request
320 struct AttributeStoreHandle
325 struct AttributeStoreHandle *next;
330 struct AttributeStoreHandle *prev;
335 struct IdpClient *client;
340 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
345 struct GNUNET_CRYPTO_EcdsaPublicKey identity_pkey;
350 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
353 * The attribute to store
355 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
358 * The attribute expiration interval
360 struct GNUNET_TIME_Relative exp;
370 * Handle for ticket consume request
372 struct ConsumeTicketOperation
377 struct ConsumeTicketOperation *next;
382 struct ConsumeTicketOperation *prev;
387 struct IdpClient *client;
395 * Ticket consume handle
397 struct RECLAIM_TICKETS_ConsumeHandle *ch;
402 * Updated attribute IDs
404 struct TicketAttributeUpdateEntry
409 struct TicketAttributeUpdateEntry *next;
414 struct TicketAttributeUpdateEntry *prev;
429 * Ticket revocation request handle
431 struct TicketRevocationOperation
436 struct TicketRevocationOperation *prev;
441 struct TicketRevocationOperation *next;
446 struct IdpClient *client;
451 struct RECLAIM_TICKETS_RevokeHandle *rh;
461 * Ticket issue operation handle
463 struct TicketIssueOperation
468 struct TicketIssueOperation *prev;
473 struct TicketIssueOperation *next;
478 struct IdpClient *client;
488 * DLL for ego handles to egos containing the RECLAIM_ATTRS in a
489 * map in json_t format
497 struct EgoEntry *next;
502 struct EgoEntry *prev;
507 struct GNUNET_IDENTITY_Ego *ego;
510 * Attribute map. Contains the attributes as json_t
512 struct GNUNET_CONTAINER_MultiHashMap *attr_map;
519 static struct IdpClient *client_list_head = NULL;
524 static struct IdpClient *client_list_tail = NULL;
528 * Cleanup attribute delete handle
530 * @param adh the attribute to cleanup
533 cleanup_adh (struct AttributeDeleteHandle *adh)
535 struct TicketRecordsEntry *le;
536 if (NULL != adh->ns_it)
537 GNUNET_NAMESTORE_zone_iteration_stop (adh->ns_it);
538 if (NULL != adh->ns_qe)
539 GNUNET_NAMESTORE_cancel (adh->ns_qe);
540 if (NULL != adh->label)
541 GNUNET_free (adh->label);
542 if (NULL != adh->claim)
543 GNUNET_free (adh->claim);
544 while (NULL != (le = adh->tickets_to_update_head)) {
545 GNUNET_CONTAINER_DLL_remove (adh->tickets_to_update_head,
546 adh->tickets_to_update_tail,
548 if (NULL != le->label)
549 GNUNET_free (le->label);
550 if (NULL != le->data)
551 GNUNET_free (le->data);
559 * Cleanup attribute store handle
561 * @param handle handle to clean up
564 cleanup_as_handle (struct AttributeStoreHandle *ash)
566 if (NULL != ash->ns_qe)
567 GNUNET_NAMESTORE_cancel (ash->ns_qe);
568 if (NULL != ash->claim)
569 GNUNET_free (ash->claim);
577 * @param idp the client to clean up
580 cleanup_client (struct IdpClient *idp)
582 struct AttributeIterator *ai;
583 struct TicketIteration *ti;
584 struct TicketRevocationOperation *rop;
585 struct TicketIssueOperation *iss;
586 struct ConsumeTicketOperation *ct;
587 struct AttributeStoreHandle *as;
588 struct AttributeDeleteHandle *adh;
590 while (NULL != (iss = idp->issue_op_head)) {
591 GNUNET_CONTAINER_DLL_remove (idp->issue_op_head, idp->issue_op_tail, iss);
594 while (NULL != (ct = idp->consume_op_head)) {
595 GNUNET_CONTAINER_DLL_remove (idp->consume_op_head,
596 idp->consume_op_tail,
599 RECLAIM_TICKETS_consume_cancel (ct->ch);
602 while (NULL != (as = idp->store_op_head)) {
603 GNUNET_CONTAINER_DLL_remove (idp->store_op_head, idp->store_op_tail, as);
604 cleanup_as_handle (as);
606 while (NULL != (adh = idp->delete_op_head)) {
607 GNUNET_CONTAINER_DLL_remove (idp->delete_op_head, idp->delete_op_tail, adh);
611 while (NULL != (ai = idp->attr_iter_head)) {
612 GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, idp->attr_iter_tail, ai);
615 while (NULL != (rop = idp->revoke_op_head)) {
616 GNUNET_CONTAINER_DLL_remove (idp->revoke_op_head, idp->revoke_op_tail, rop);
618 RECLAIM_TICKETS_revoke_cancel (rop->rh);
621 while (NULL != (ti = idp->ticket_iter_head)) {
622 GNUNET_CONTAINER_DLL_remove (idp->ticket_iter_head,
623 idp->ticket_iter_tail,
625 if (NULL != ti->iter)
626 RECLAIM_TICKETS_iteration_stop (ti->iter);
639 struct IdpClient *cl;
640 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
642 while (NULL != (cl = client_list_head))
644 GNUNET_CONTAINER_DLL_remove (client_list_head,
649 RECLAIM_TICKETS_deinit ();
650 if (NULL != timeout_task)
651 GNUNET_SCHEDULER_cancel (timeout_task);
652 if (NULL != update_task)
653 GNUNET_SCHEDULER_cancel (update_task);
654 if (NULL != identity_handle)
655 GNUNET_IDENTITY_disconnect (identity_handle);
657 GNUNET_NAMESTORE_disconnect (nsh);
667 do_shutdown (void *cls)
669 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down...\n");
675 * Sends a ticket result message to the client
677 * @param client the client to send to
678 * @param r_id the request message ID to reply to
679 * @param ticket the ticket to include (may be NULL)
680 * @param success the success status of the request
683 send_ticket_result (const struct IdpClient *client,
685 const struct GNUNET_RECLAIM_Ticket *ticket,
688 struct TicketResultMessage *irm;
689 struct GNUNET_MQ_Envelope *env;
690 struct GNUNET_RECLAIM_Ticket *ticket_buf;
692 if (NULL != ticket) {
693 env = GNUNET_MQ_msg_extra (irm,
694 sizeof (struct GNUNET_RECLAIM_Ticket),
695 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
696 ticket_buf = (struct GNUNET_RECLAIM_Ticket *)&irm[1];
697 *ticket_buf = *ticket;
699 env = GNUNET_MQ_msg (irm, GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
701 // TODO add success member
702 irm->id = htonl (r_id);
703 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending TICKET_RESULT message\n");
704 GNUNET_MQ_send (client->mq, env);
709 * Issue ticket result
711 * @param cls out ticket issue operation handle
712 * @param ticket the issued ticket
713 * @param success issue success status (GNUNET_OK if successful)
714 * @param emsg error message (NULL of success is GNUNET_OK)
717 issue_ticket_result_cb (void *cls,
718 struct GNUNET_RECLAIM_Ticket *ticket,
722 struct TicketIssueOperation *tio = cls;
723 if (GNUNET_OK != success) {
724 send_ticket_result (tio->client, tio->r_id, NULL, GNUNET_SYSERR);
725 GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head,
726 tio->client->issue_op_tail,
729 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error issuing ticket: %s\n", emsg);
732 send_ticket_result (tio->client, tio->r_id, ticket, GNUNET_SYSERR);
733 GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head,
734 tio->client->issue_op_tail,
741 * Check issue ticket message
744 * @im message to check
745 * @return GNUNET_OK if message is ok
748 check_issue_ticket_message (void *cls, const struct IssueTicketMessage *im)
752 size = ntohs (im->header.size);
753 if (size <= sizeof (struct IssueTicketMessage)) {
755 return GNUNET_SYSERR;
762 * Handle ticket issue message
764 * @param cls our client
765 * @param im the message
768 handle_issue_ticket_message (void *cls, const struct IssueTicketMessage *im)
770 struct TicketIssueOperation *tio;
771 struct IdpClient *idp = cls;
772 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
775 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ISSUE_TICKET message\n");
776 tio = GNUNET_new (struct TicketIssueOperation);
777 attrs_len = ntohs (im->attr_len);
778 attrs = GNUNET_RECLAIM_ATTRIBUTE_list_deserialize ((char *)&im[1], attrs_len);
779 tio->r_id = ntohl (im->id);
781 GNUNET_CONTAINER_DLL_insert (idp->issue_op_head, idp->issue_op_tail, tio);
782 RECLAIM_TICKETS_issue (&im->identity,
785 &issue_ticket_result_cb,
787 GNUNET_SERVICE_client_continue (idp->client);
788 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (attrs);
793 /**********************************************************
795 **********************************************************/
798 * Handles revocation result
800 * @param cls our revocation operation handle
801 * @param success revocation result (GNUNET_OK if successful)
804 revoke_result_cb (void *cls, int32_t success)
806 struct TicketRevocationOperation *rop = cls;
807 struct GNUNET_MQ_Envelope *env;
808 struct RevokeTicketResultMessage *trm;
810 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending REVOKE_TICKET_RESULT message\n");
812 env = GNUNET_MQ_msg (trm, GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT);
813 trm->id = htonl (rop->r_id);
814 trm->success = htonl (success);
815 GNUNET_MQ_send (rop->client->mq, env);
816 GNUNET_CONTAINER_DLL_remove (rop->client->revoke_op_head,
817 rop->client->revoke_op_tail,
824 * Check revocation message format
827 * @param im the message to check
828 * @return GNUNET_OK if message is ok
831 check_revoke_ticket_message (void *cls, const struct RevokeTicketMessage *im)
835 size = ntohs (im->header.size);
836 if (size <= sizeof (struct RevokeTicketMessage)) {
838 return GNUNET_SYSERR;
845 * Handle a revocation message to a ticket.
847 * @param cls our client
848 * @param rm the message to handle
851 handle_revoke_ticket_message (void *cls, const struct RevokeTicketMessage *rm)
853 struct TicketRevocationOperation *rop;
854 struct IdpClient *idp = cls;
855 struct GNUNET_RECLAIM_Ticket *ticket;
857 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received REVOKE_TICKET message\n");
858 rop = GNUNET_new (struct TicketRevocationOperation);
859 ticket = (struct GNUNET_RECLAIM_Ticket *)&rm[1];
860 rop->r_id = ntohl (rm->id);
862 GNUNET_CONTAINER_DLL_insert (idp->revoke_op_head, idp->revoke_op_tail, rop);
864 = RECLAIM_TICKETS_revoke (ticket, &rm->identity, &revoke_result_cb, rop);
865 GNUNET_SERVICE_client_continue (idp->client);
870 * Handle a ticket consume result
872 * @param cls our consume ticket operation handle
873 * @param identity the attribute authority
874 * @param attrs the attribute/claim list
875 * @param success GNUNET_OK if successful
876 * @param emsg error message (NULL if success=GNUNET_OK)
879 consume_result_cb (void *cls,
880 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
881 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
885 struct ConsumeTicketOperation *cop = cls;
886 struct ConsumeTicketResultMessage *crm;
887 struct GNUNET_MQ_Envelope *env;
890 if (GNUNET_OK != success) {
891 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error consuming ticket: %s\n", emsg);
893 attrs_len = GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (attrs);
894 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending CONSUME_TICKET_RESULT message\n");
895 env = GNUNET_MQ_msg_extra (crm,
897 GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT);
898 crm->id = htonl (cop->r_id);
899 crm->attrs_len = htons (attrs_len);
900 crm->identity = *identity;
901 crm->result = htonl (success);
902 data_tmp = (char *)&crm[1];
903 GNUNET_RECLAIM_ATTRIBUTE_list_serialize (attrs, data_tmp);
904 GNUNET_MQ_send (cop->client->mq, env);
905 GNUNET_CONTAINER_DLL_remove (cop->client->consume_op_head,
906 cop->client->consume_op_tail,
913 * Check a consume ticket message
916 * @param cm the message to handle
919 check_consume_ticket_message (void *cls, const struct ConsumeTicketMessage *cm)
923 size = ntohs (cm->header.size);
924 if (size <= sizeof (struct ConsumeTicketMessage)) {
926 return GNUNET_SYSERR;
933 * Handle a consume ticket message
935 * @param cls our client handle
936 * @cm the message to handle
939 handle_consume_ticket_message (void *cls, const struct ConsumeTicketMessage *cm)
941 struct ConsumeTicketOperation *cop;
942 struct GNUNET_RECLAIM_Ticket *ticket;
943 struct IdpClient *idp = cls;
945 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received CONSUME_TICKET message\n");
946 cop = GNUNET_new (struct ConsumeTicketOperation);
947 cop->r_id = ntohl (cm->id);
949 ticket = (struct GNUNET_RECLAIM_Ticket *)&cm[1];
951 = RECLAIM_TICKETS_consume (&cm->identity, ticket, &consume_result_cb, cop);
952 GNUNET_CONTAINER_DLL_insert (idp->consume_op_head, idp->consume_op_tail, cop);
953 GNUNET_SERVICE_client_continue (idp->client);
956 /*****************************************
958 *****************************************/
962 * Attribute store result handler
964 * @param cls our attribute store handle
965 * @param success GNUNET_OK if successful
966 * @param emsg error message (NULL if success=GNUNET_OK)
969 attr_store_cont (void *cls, int32_t success, const char *emsg)
971 struct AttributeStoreHandle *ash = cls;
972 struct GNUNET_MQ_Envelope *env;
973 struct SuccessResultMessage *acr_msg;
976 GNUNET_CONTAINER_DLL_remove (ash->client->store_op_head,
977 ash->client->store_op_tail,
980 if (GNUNET_SYSERR == success) {
981 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
982 "Failed to store attribute %s\n",
984 cleanup_as_handle (ash);
985 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
989 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
990 env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
991 acr_msg->id = htonl (ash->r_id);
992 acr_msg->op_result = htonl (GNUNET_OK);
993 GNUNET_MQ_send (ash->client->mq, env);
994 cleanup_as_handle (ash);
999 * Add a new attribute
1001 * @param cls the AttributeStoreHandle
1004 attr_store_task (void *cls)
1006 struct AttributeStoreHandle *ash = cls;
1007 struct GNUNET_GNSRECORD_Data rd[1];
1012 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Storing attribute\n");
1013 buf_size = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (ash->claim);
1014 buf = GNUNET_malloc (buf_size);
1015 // Give the ash a new id if unset
1016 if (0 == ash->claim->id)
1018 = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX);
1019 GNUNET_RECLAIM_ATTRIBUTE_serialize (ash->claim, buf);
1021 = GNUNET_STRINGS_data_to_string_alloc (&ash->claim->id, sizeof (uint64_t));
1022 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting with label %s\n", label);
1024 rd[0].data_size = buf_size;
1026 rd[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR;
1027 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1028 rd[0].expiration_time = ash->exp.rel_value_us;
1029 ash->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1041 * Check an attribute store message
1044 * @param sam the message to check
1047 check_attribute_store_message (void *cls,
1048 const struct AttributeStoreMessage *sam)
1052 size = ntohs (sam->header.size);
1053 if (size <= sizeof (struct AttributeStoreMessage)) {
1055 return GNUNET_SYSERR;
1062 * Handle an attribute store message
1064 * @param cls our client
1065 * @param sam the message to handle
1068 handle_attribute_store_message (void *cls,
1069 const struct AttributeStoreMessage *sam)
1071 struct AttributeStoreHandle *ash;
1072 struct IdpClient *idp = cls;
1074 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTRIBUTE_STORE message\n");
1076 data_len = ntohs (sam->attr_len);
1078 ash = GNUNET_new (struct AttributeStoreHandle);
1079 ash->claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize ((char *)&sam[1], data_len);
1081 ash->r_id = ntohl (sam->id);
1082 ash->identity = sam->identity;
1083 ash->exp.rel_value_us = GNUNET_ntohll (sam->exp);
1084 GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity, &ash->identity_pkey);
1086 GNUNET_SERVICE_client_continue (idp->client);
1088 GNUNET_CONTAINER_DLL_insert (idp->store_op_head, idp->store_op_tail, ash);
1089 GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
1094 * Send a deletion success response
1096 * @param adh our attribute deletion handle
1097 * @param success the success status
1100 send_delete_response (struct AttributeDeleteHandle *adh, int32_t success)
1102 struct GNUNET_MQ_Envelope *env;
1103 struct SuccessResultMessage *acr_msg;
1105 GNUNET_CONTAINER_DLL_remove (adh->client->delete_op_head,
1106 adh->client->delete_op_tail,
1109 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
1110 env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
1111 acr_msg->id = htonl (adh->r_id);
1112 acr_msg->op_result = htonl (success);
1113 GNUNET_MQ_send (adh->client->mq, env);
1118 * Namestore iteration within attribute deletion.
1119 * We need to reissue tickets with the deleted attribute removed.
1121 * @param cls our attribute deletion handle
1122 * @param zone the private key of the ticket issuer
1123 * @param label the label of the record
1124 * @param rd_count number of records
1125 * @param rd record data
1128 ticket_iter (void *cls,
1129 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1131 unsigned int rd_count,
1132 const struct GNUNET_GNSRECORD_Data *rd)
1134 struct AttributeDeleteHandle *adh = cls;
1135 struct TicketRecordsEntry *le;
1136 int has_changed = GNUNET_NO;
1138 for (int i = 0; i < rd_count; i++) {
1139 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF != rd[i].record_type)
1141 if (0 != memcmp (rd[i].data, &adh->claim->id, sizeof (uint64_t)))
1143 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1144 "Attribute to delete found (%s)\n",
1146 has_changed = GNUNET_YES;
1149 if (GNUNET_YES == has_changed) {
1150 le = GNUNET_new (struct TicketRecordsEntry);
1151 le->data_size = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
1152 le->data = GNUNET_malloc (le->data_size);
1153 le->rd_count = rd_count;
1154 le->label = GNUNET_strdup (label);
1155 GNUNET_GNSRECORD_records_serialize (rd_count, rd, le->data_size, le->data);
1156 GNUNET_CONTAINER_DLL_insert (adh->tickets_to_update_head,
1157 adh->tickets_to_update_tail,
1160 GNUNET_NAMESTORE_zone_iterator_next (adh->ns_it, 1);
1165 * Recursion prototype for function
1166 * @param cls our deletion handle
1169 update_tickets (void *cls);
1173 * Callback called when a ticket was updated
1175 * @param cls our attribute deletion handle
1176 * @param success GNUNET_OK if successful
1177 * @param emsg error message (NULL if success=GNUNET_OK)
1180 ticket_updated (void *cls, int32_t success, const char *emsg)
1182 struct AttributeDeleteHandle *adh = cls;
1184 GNUNET_SCHEDULER_add_now (&update_tickets, adh);
1189 * Update tickets: Remove shared attribute which has just been deleted.
1190 * This method is called recursively until all tickets are processed.
1191 * Eventually, the updated tickets are stored using ``update_tickets''.
1193 * @param cls our attribute deletion handle
1196 update_tickets (void *cls)
1198 struct AttributeDeleteHandle *adh = cls;
1199 struct TicketRecordsEntry *le;
1200 if (NULL == adh->tickets_to_update_head) {
1201 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1202 "Finished updatding tickets, success\n");
1203 send_delete_response (adh, GNUNET_OK);
1207 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1209 adh->tickets_to_update_head->label);
1210 le = adh->tickets_to_update_head;
1211 GNUNET_CONTAINER_DLL_remove (adh->tickets_to_update_head,
1212 adh->tickets_to_update_tail,
1214 struct GNUNET_GNSRECORD_Data rd[le->rd_count];
1215 struct GNUNET_GNSRECORD_Data rd_new[le->rd_count - 1];
1216 GNUNET_GNSRECORD_records_deserialize (le->data_size,
1221 for (int i = 0; i < le->rd_count; i++) {
1222 if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF == rd[i].record_type)
1223 && (0 == memcmp (rd[i].data, &adh->claim->id, sizeof (uint64_t))))
1228 adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1235 GNUNET_free (le->label);
1236 GNUNET_free (le->data);
1242 * Done collecting affected tickets, start updating.
1244 * @param cls our attribute deletion handle
1247 ticket_iter_fin (void *cls)
1249 struct AttributeDeleteHandle *adh = cls;
1251 GNUNET_SCHEDULER_add_now (&update_tickets, adh);
1256 * Error collecting affected tickets. Abort.
1258 * @param cls our attribute deletion handle
1261 ticket_iter_err (void *cls)
1263 struct AttributeDeleteHandle *adh = cls;
1265 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1266 "Namestore error on delete %s\n",
1268 send_delete_response (adh, GNUNET_SYSERR);
1274 * Start processing tickets which may still contain reference to deleted
1277 * @param cls attribute deletion handle
1280 start_ticket_update (void *cls)
1282 struct AttributeDeleteHandle *adh = cls;
1283 adh->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh,
1295 * Attribute deleted callback
1297 * @param cls our handle
1298 * @param success success status
1299 * @param emsg error message (NULL if success=GNUNET_OK)
1302 attr_delete_cont (void *cls, int32_t success, const char *emsg)
1304 struct AttributeDeleteHandle *adh = cls;
1306 if (GNUNET_SYSERR == success) {
1307 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1308 "Error deleting attribute %s\n",
1310 send_delete_response (adh, GNUNET_SYSERR);
1314 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating tickets...\n");
1315 GNUNET_SCHEDULER_add_now (&start_ticket_update, adh);
1320 * Check attribute delete message format
1323 * @dam message to check
1326 check_attribute_delete_message (void *cls,
1327 const struct AttributeDeleteMessage *dam)
1331 size = ntohs (dam->header.size);
1332 if (size <= sizeof (struct AttributeDeleteMessage)) {
1334 return GNUNET_SYSERR;
1341 * Handle attribute deletion
1343 * @param cls our client
1344 * @param dam deletion message
1347 handle_attribute_delete_message (void *cls,
1348 const struct AttributeDeleteMessage *dam)
1350 struct AttributeDeleteHandle *adh;
1351 struct IdpClient *idp = cls;
1353 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTRIBUTE_DELETE message\n");
1355 data_len = ntohs (dam->attr_len);
1357 adh = GNUNET_new (struct AttributeDeleteHandle);
1358 adh->claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize ((char *)&dam[1], data_len);
1360 adh->r_id = ntohl (dam->id);
1361 adh->identity = dam->identity;
1363 = GNUNET_STRINGS_data_to_string_alloc (&adh->claim->id, sizeof (uint64_t));
1364 GNUNET_SERVICE_client_continue (idp->client);
1366 GNUNET_CONTAINER_DLL_insert (idp->delete_op_head, idp->delete_op_tail, adh);
1367 adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1377 /*************************************************
1378 * Attrubute iteration
1379 *************************************************/
1383 * Done iterating over attributes
1385 * @param cls our iterator handle
1388 attr_iter_finished (void *cls)
1390 struct AttributeIterator *ai = cls;
1391 struct GNUNET_MQ_Envelope *env;
1392 struct AttributeResultMessage *arm;
1394 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending ATTRIBUTE_RESULT message\n");
1395 env = GNUNET_MQ_msg (arm, GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
1396 arm->id = htonl (ai->request_id);
1397 arm->attr_len = htons (0);
1398 GNUNET_MQ_send (ai->client->mq, env);
1399 GNUNET_CONTAINER_DLL_remove (ai->client->attr_iter_head,
1400 ai->client->attr_iter_tail,
1406 * Error iterating over attributes. Abort.
1408 * @param cls our attribute iteration handle
1411 attr_iter_error (void *cls)
1413 struct AttributeIterator *ai = cls;
1415 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to iterate over attributes\n");
1416 attr_iter_finished (ai);
1421 * Got record. Return if it is an attribute.
1423 * @param cls our attribute iterator
1424 * @param zone zone we are iterating
1425 * @param label label of the records
1426 * @param rd_count record count
1430 attr_iter_cb (void *cls,
1431 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1433 unsigned int rd_count,
1434 const struct GNUNET_GNSRECORD_Data *rd)
1436 struct AttributeIterator *ai = cls;
1437 struct AttributeResultMessage *arm;
1438 struct GNUNET_MQ_Envelope *env;
1441 if (rd_count != 1) {
1442 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1446 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR != rd->record_type) {
1447 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1450 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found attribute under: %s\n", label);
1451 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending ATTRIBUTE_RESULT message\n");
1452 env = GNUNET_MQ_msg_extra (arm,
1454 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
1455 arm->id = htonl (ai->request_id);
1456 arm->attr_len = htons (rd->data_size);
1457 GNUNET_CRYPTO_ecdsa_key_get_public (zone, &arm->identity);
1458 data_tmp = (char *)&arm[1];
1459 GNUNET_memcpy (data_tmp, rd->data, rd->data_size);
1460 GNUNET_MQ_send (ai->client->mq, env);
1465 * Iterate over zone to get attributes
1467 * @param cls our client
1468 * @param ais_msg the iteration message to start
1471 handle_iteration_start (void *cls,
1472 const struct AttributeIterationStartMessage *ais_msg)
1474 struct IdpClient *idp = cls;
1475 struct AttributeIterator *ai;
1477 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1478 "Received ATTRIBUTE_ITERATION_START message\n");
1479 ai = GNUNET_new (struct AttributeIterator);
1480 ai->request_id = ntohl (ais_msg->id);
1482 ai->identity = ais_msg->identity;
1484 GNUNET_CONTAINER_DLL_insert (idp->attr_iter_head, idp->attr_iter_tail, ai);
1485 ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh,
1491 &attr_iter_finished,
1493 GNUNET_SERVICE_client_continue (idp->client);
1498 * Handle iteration stop message from client
1500 * @param cls the client
1501 * @param ais_msg the stop message
1504 handle_iteration_stop (void *cls,
1505 const struct AttributeIterationStopMessage *ais_msg)
1507 struct IdpClient *idp = cls;
1508 struct AttributeIterator *ai;
1511 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1512 "Received `%s' message\n",
1513 "ATTRIBUTE_ITERATION_STOP");
1514 rid = ntohl (ais_msg->id);
1515 for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
1516 if (ai->request_id == rid)
1520 GNUNET_SERVICE_client_drop (idp->client);
1523 GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, idp->attr_iter_tail, ai);
1525 GNUNET_SERVICE_client_continue (idp->client);
1530 * Client requests next attribute from iterator
1532 * @param cls the client
1533 * @param ais_msg the message
1536 handle_iteration_next (void *cls,
1537 const struct AttributeIterationNextMessage *ais_msg)
1539 struct IdpClient *idp = cls;
1540 struct AttributeIterator *ai;
1543 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1544 "Received ATTRIBUTE_ITERATION_NEXT message\n");
1545 rid = ntohl (ais_msg->id);
1546 for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
1547 if (ai->request_id == rid)
1551 GNUNET_SERVICE_client_drop (idp->client);
1554 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1555 GNUNET_SERVICE_client_continue (idp->client);
1558 /******************************************************
1560 ******************************************************/
1563 * Got a ticket. Return to client
1565 * @param cls our ticket iterator
1566 * @param ticket the ticket
1569 ticket_iter_cb (void *cls, struct GNUNET_RECLAIM_Ticket *ticket)
1571 struct TicketIteration *ti = cls;
1572 struct GNUNET_MQ_Envelope *env;
1573 struct TicketResultMessage *trm;
1575 if (NULL == ticket) {
1576 /* send empty response to indicate end of list */
1577 env = GNUNET_MQ_msg (trm, GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
1578 GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head,
1579 ti->client->ticket_iter_tail,
1582 env = GNUNET_MQ_msg_extra (trm,
1583 sizeof (struct GNUNET_RECLAIM_Ticket),
1584 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
1585 memcpy (&trm[1], ticket, sizeof (struct GNUNET_RECLAIM_Ticket));
1587 trm->id = htonl (ti->r_id);
1588 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending TICKET_RESULT message\n");
1589 GNUNET_MQ_send (ti->client->mq, env);
1596 * Client requests a ticket iteration
1598 * @param cls the client
1599 * @param tis_msg the iteration request message
1602 handle_ticket_iteration_start (
1604 const struct TicketIterationStartMessage *tis_msg)
1606 struct IdpClient *client = cls;
1607 struct TicketIteration *ti;
1609 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1610 "Received TICKET_ITERATION_START message\n");
1611 ti = GNUNET_new (struct TicketIteration);
1612 ti->r_id = ntohl (tis_msg->id);
1613 ti->client = client;
1615 GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
1616 client->ticket_iter_tail,
1619 = RECLAIM_TICKETS_iteration_start (&tis_msg->identity, &ticket_iter_cb, ti);
1620 GNUNET_SERVICE_client_continue (client->client);
1625 * Client has had enough tickets
1627 * @param cls the client
1628 * @param tis_msg the stop message
1631 handle_ticket_iteration_stop (void *cls,
1632 const struct TicketIterationStopMessage *tis_msg)
1634 struct IdpClient *client = cls;
1635 struct TicketIteration *ti;
1638 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1639 "Received `%s' message\n",
1640 "TICKET_ITERATION_STOP");
1641 rid = ntohl (tis_msg->id);
1642 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
1643 if (ti->r_id == rid)
1647 GNUNET_SERVICE_client_drop (client->client);
1650 RECLAIM_TICKETS_iteration_stop (ti->iter);
1651 GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
1652 client->ticket_iter_tail,
1655 GNUNET_SERVICE_client_continue (client->client);
1660 * Client requests next result.
1662 * @param cls the client
1663 * @param tis_msg the message
1666 handle_ticket_iteration_next (void *cls,
1667 const struct TicketIterationNextMessage *tis_msg)
1669 struct IdpClient *client = cls;
1670 struct TicketIteration *ti;
1673 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1674 "Received TICKET_ITERATION_NEXT message\n");
1675 rid = ntohl (tis_msg->id);
1676 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
1677 if (ti->r_id == rid)
1681 GNUNET_SERVICE_client_drop (client->client);
1684 RECLAIM_TICKETS_iteration_next (ti->iter);
1685 GNUNET_SERVICE_client_continue (client->client);
1690 * Main function that will be run
1692 * @param cls closure
1693 * @param c the configuration used
1694 * @param server the service handle
1698 const struct GNUNET_CONFIGURATION_Handle *c,
1699 struct GNUNET_SERVICE_Handle *server)
1703 if (GNUNET_OK != RECLAIM_TICKETS_init (cfg)) {
1704 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1705 "Unable to initialize TICKETS subsystem.\n");
1706 GNUNET_SCHEDULER_shutdown ();
1709 // Connect to identity and namestore services
1710 nsh = GNUNET_NAMESTORE_connect (cfg);
1712 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
1713 "error connecting to namestore");
1716 identity_handle = GNUNET_IDENTITY_connect (cfg, NULL, NULL);
1718 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
1723 * Called whenever a client is disconnected.
1725 * @param cls closure
1726 * @param client identification of the client
1727 * @param app_ctx @a client
1730 client_disconnect_cb (void *cls,
1731 struct GNUNET_SERVICE_Client *client,
1734 struct IdpClient *idp = app_ctx;
1735 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client);
1736 GNUNET_CONTAINER_DLL_remove (client_list_head,
1739 cleanup_client (idp);
1744 * Add a client to our list of active clients.
1747 * @param client client to add
1748 * @param mq message queue for @a client
1749 * @return internal namestore client structure for this client
1752 client_connect_cb (void *cls,
1753 struct GNUNET_SERVICE_Client *client,
1754 struct GNUNET_MQ_Handle *mq)
1756 struct IdpClient *idp;
1757 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
1758 idp = GNUNET_new (struct IdpClient);
1759 idp->client = client;
1761 GNUNET_CONTAINER_DLL_insert (client_list_head,
1769 * Define "main" method using service macro.
1771 GNUNET_SERVICE_MAIN (
1773 GNUNET_SERVICE_OPTION_NONE,
1776 &client_disconnect_cb,
1778 GNUNET_MQ_hd_var_size (attribute_store_message,
1779 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE,
1780 struct AttributeStoreMessage,
1782 GNUNET_MQ_hd_var_size (attribute_delete_message,
1783 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_DELETE,
1784 struct AttributeDeleteMessage,
1786 GNUNET_MQ_hd_fixed_size (
1788 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_START,
1789 struct AttributeIterationStartMessage,
1791 GNUNET_MQ_hd_fixed_size (iteration_next,
1792 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT,
1793 struct AttributeIterationNextMessage,
1795 GNUNET_MQ_hd_fixed_size (iteration_stop,
1796 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP,
1797 struct AttributeIterationStopMessage,
1799 GNUNET_MQ_hd_var_size (issue_ticket_message,
1800 GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET,
1801 struct IssueTicketMessage,
1803 GNUNET_MQ_hd_var_size (consume_ticket_message,
1804 GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET,
1805 struct ConsumeTicketMessage,
1807 GNUNET_MQ_hd_fixed_size (ticket_iteration_start,
1808 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_START,
1809 struct TicketIterationStartMessage,
1811 GNUNET_MQ_hd_fixed_size (ticket_iteration_next,
1812 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_NEXT,
1813 struct TicketIterationNextMessage,
1815 GNUNET_MQ_hd_fixed_size (ticket_iteration_stop,
1816 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_STOP,
1817 struct TicketIterationStopMessage,
1819 GNUNET_MQ_hd_var_size (revoke_ticket_message,
1820 GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET,
1821 struct RevokeTicketMessage,
1823 GNUNET_MQ_handler_end ());
1824 /* end of gnunet-service-reclaim.c */