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);
716 /**********************************************************
718 **********************************************************/
721 * Handles revocation result
723 * @param cls our revocation operation handle
724 * @param success revocation result (GNUNET_OK if successful)
727 revoke_result_cb (void *cls, int32_t success)
729 struct TicketRevocationOperation *rop = cls;
730 struct GNUNET_MQ_Envelope *env;
731 struct RevokeTicketResultMessage *trm;
733 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
734 "Sending REVOKE_TICKET_RESULT message\n");
736 env = GNUNET_MQ_msg (trm, GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT);
737 trm->id = htonl (rop->r_id);
738 trm->success = htonl (success);
739 GNUNET_MQ_send (rop->client->mq, env);
740 GNUNET_CONTAINER_DLL_remove (rop->client->revoke_op_head,
741 rop->client->revoke_op_tail,
748 * Check revocation message format
751 * @param im the message to check
752 * @return GNUNET_OK if message is ok
755 check_revoke_ticket_message (void *cls, const struct RevokeTicketMessage *im)
759 size = ntohs (im->header.size);
760 if (size != sizeof(struct RevokeTicketMessage))
763 return GNUNET_SYSERR;
770 * Handle a revocation message to a ticket.
772 * @param cls our client
773 * @param rm the message to handle
776 handle_revoke_ticket_message (void *cls, const struct RevokeTicketMessage *rm)
778 struct TicketRevocationOperation *rop;
779 struct IdpClient *idp = cls;
781 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received REVOKE_TICKET message\n");
782 rop = GNUNET_new (struct TicketRevocationOperation);
783 rop->r_id = ntohl (rm->id);
785 GNUNET_CONTAINER_DLL_insert (idp->revoke_op_head, idp->revoke_op_tail, rop);
787 = RECLAIM_TICKETS_revoke (&rm->ticket, &rm->identity, &revoke_result_cb,
789 GNUNET_SERVICE_client_continue (idp->client);
794 * Handle a ticket consume result
796 * @param cls our consume ticket operation handle
797 * @param identity the attribute authority
798 * @param attrs the attribute/claim list
799 * @param success GNUNET_OK if successful
800 * @param emsg error message (NULL if success=GNUNET_OK)
803 consume_result_cb (void *cls,
804 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
805 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
809 struct ConsumeTicketOperation *cop = cls;
810 struct ConsumeTicketResultMessage *crm;
811 struct GNUNET_MQ_Envelope *env;
815 if (GNUNET_OK != success)
817 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error consuming ticket: %s\n", emsg);
819 attrs_len = GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (attrs);
820 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
821 "Sending CONSUME_TICKET_RESULT message\n");
822 env = GNUNET_MQ_msg_extra (crm,
824 GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT);
825 crm->id = htonl (cop->r_id);
826 crm->attrs_len = htons (attrs_len);
827 crm->identity = *identity;
828 crm->result = htonl (success);
829 data_tmp = (char *) &crm[1];
830 GNUNET_RECLAIM_ATTRIBUTE_list_serialize (attrs, data_tmp);
831 GNUNET_MQ_send (cop->client->mq, env);
832 GNUNET_CONTAINER_DLL_remove (cop->client->consume_op_head,
833 cop->client->consume_op_tail,
840 * Check a consume ticket message
843 * @param cm the message to handle
846 check_consume_ticket_message (void *cls, const struct ConsumeTicketMessage *cm)
850 size = ntohs (cm->header.size);
851 if (size != sizeof(struct ConsumeTicketMessage))
854 return GNUNET_SYSERR;
861 * Handle a consume ticket message
863 * @param cls our client handle
864 * @cm the message to handle
867 handle_consume_ticket_message (void *cls, const struct ConsumeTicketMessage *cm)
869 struct ConsumeTicketOperation *cop;
870 struct IdpClient *idp = cls;
872 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received CONSUME_TICKET message\n");
873 cop = GNUNET_new (struct ConsumeTicketOperation);
874 cop->r_id = ntohl (cm->id);
877 = RECLAIM_TICKETS_consume (&cm->identity, &cm->ticket, &consume_result_cb,
879 GNUNET_CONTAINER_DLL_insert (idp->consume_op_head, idp->consume_op_tail, cop);
880 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,
1359 * Error iterating over attributes. Abort.
1361 * @param cls our attribute iteration handle
1364 attr_iter_error (void *cls)
1366 struct AttributeIterator *ai = cls;
1368 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to iterate over attributes\n");
1369 attr_iter_finished (ai);
1374 * Got record. Return if it is an attribute.
1376 * @param cls our attribute iterator
1377 * @param zone zone we are iterating
1378 * @param label label of the records
1379 * @param rd_count record count
1383 attr_iter_cb (void *cls,
1384 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1386 unsigned int rd_count,
1387 const struct GNUNET_GNSRECORD_Data *rd)
1389 struct AttributeIterator *ai = cls;
1390 struct AttributeResultMessage *arm;
1391 struct GNUNET_MQ_Envelope *env;
1396 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1400 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR != rd->record_type)
1402 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1405 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found attribute under: %s\n", label);
1406 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending ATTRIBUTE_RESULT message\n");
1407 env = GNUNET_MQ_msg_extra (arm,
1409 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
1410 arm->id = htonl (ai->request_id);
1411 arm->attr_len = htons (rd->data_size);
1412 GNUNET_CRYPTO_ecdsa_key_get_public (zone, &arm->identity);
1413 data_tmp = (char *) &arm[1];
1414 GNUNET_memcpy (data_tmp, rd->data, rd->data_size);
1415 GNUNET_MQ_send (ai->client->mq, env);
1420 * Iterate over zone to get attributes
1422 * @param cls our client
1423 * @param ais_msg the iteration message to start
1426 handle_iteration_start (void *cls,
1427 const struct AttributeIterationStartMessage *ais_msg)
1429 struct IdpClient *idp = cls;
1430 struct AttributeIterator *ai;
1432 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1433 "Received ATTRIBUTE_ITERATION_START message\n");
1434 ai = GNUNET_new (struct AttributeIterator);
1435 ai->request_id = ntohl (ais_msg->id);
1437 ai->identity = ais_msg->identity;
1439 GNUNET_CONTAINER_DLL_insert (idp->attr_iter_head, idp->attr_iter_tail, ai);
1440 ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh,
1446 &attr_iter_finished,
1448 GNUNET_SERVICE_client_continue (idp->client);
1453 * Handle iteration stop message from client
1455 * @param cls the client
1456 * @param ais_msg the stop message
1459 handle_iteration_stop (void *cls,
1460 const struct AttributeIterationStopMessage *ais_msg)
1462 struct IdpClient *idp = cls;
1463 struct AttributeIterator *ai;
1466 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1467 "Received `%s' message\n",
1468 "ATTRIBUTE_ITERATION_STOP");
1469 rid = ntohl (ais_msg->id);
1470 for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
1471 if (ai->request_id == rid)
1476 GNUNET_SERVICE_client_drop (idp->client);
1479 GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, idp->attr_iter_tail, ai);
1481 GNUNET_SERVICE_client_continue (idp->client);
1486 * Client requests next attribute from iterator
1488 * @param cls the client
1489 * @param ais_msg the message
1492 handle_iteration_next (void *cls,
1493 const struct AttributeIterationNextMessage *ais_msg)
1495 struct IdpClient *idp = cls;
1496 struct AttributeIterator *ai;
1499 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1500 "Received ATTRIBUTE_ITERATION_NEXT message\n");
1501 rid = ntohl (ais_msg->id);
1502 for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
1503 if (ai->request_id == rid)
1508 GNUNET_SERVICE_client_drop (idp->client);
1511 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1512 GNUNET_SERVICE_client_continue (idp->client);
1515 /******************************************************
1517 ******************************************************/
1520 * Got a ticket. Return to client
1522 * @param cls our ticket iterator
1523 * @param ticket the ticket
1526 ticket_iter_cb (void *cls, struct GNUNET_RECLAIM_Ticket *ticket)
1528 struct TicketIteration *ti = cls;
1529 struct GNUNET_MQ_Envelope *env;
1530 struct TicketResultMessage *trm;
1532 env = GNUNET_MQ_msg (trm, GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
1535 /* send empty response to indicate end of list */
1536 GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head,
1537 ti->client->ticket_iter_tail,
1542 trm->ticket = *ticket;
1544 trm->id = htonl (ti->r_id);
1545 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending TICKET_RESULT message\n");
1546 GNUNET_MQ_send (ti->client->mq, env);
1553 * Client requests a ticket iteration
1555 * @param cls the client
1556 * @param tis_msg the iteration request message
1559 handle_ticket_iteration_start (
1561 const struct TicketIterationStartMessage *tis_msg)
1563 struct IdpClient *client = cls;
1564 struct TicketIteration *ti;
1566 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1567 "Received TICKET_ITERATION_START message\n");
1568 ti = GNUNET_new (struct TicketIteration);
1569 ti->r_id = ntohl (tis_msg->id);
1570 ti->client = client;
1572 GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
1573 client->ticket_iter_tail,
1576 = RECLAIM_TICKETS_iteration_start (&tis_msg->identity, &ticket_iter_cb, ti);
1577 GNUNET_SERVICE_client_continue (client->client);
1582 * Client has had enough tickets
1584 * @param cls the client
1585 * @param tis_msg the stop message
1588 handle_ticket_iteration_stop (void *cls,
1589 const struct TicketIterationStopMessage *tis_msg)
1591 struct IdpClient *client = cls;
1592 struct TicketIteration *ti;
1595 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1596 "Received `%s' message\n",
1597 "TICKET_ITERATION_STOP");
1598 rid = ntohl (tis_msg->id);
1599 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
1600 if (ti->r_id == rid)
1605 GNUNET_SERVICE_client_drop (client->client);
1608 RECLAIM_TICKETS_iteration_stop (ti->iter);
1609 GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
1610 client->ticket_iter_tail,
1613 GNUNET_SERVICE_client_continue (client->client);
1618 * Client requests next result.
1620 * @param cls the client
1621 * @param tis_msg the message
1624 handle_ticket_iteration_next (void *cls,
1625 const struct TicketIterationNextMessage *tis_msg)
1627 struct IdpClient *client = cls;
1628 struct TicketIteration *ti;
1631 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1632 "Received TICKET_ITERATION_NEXT message\n");
1633 rid = ntohl (tis_msg->id);
1634 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
1635 if (ti->r_id == rid)
1640 GNUNET_SERVICE_client_drop (client->client);
1643 RECLAIM_TICKETS_iteration_next (ti->iter);
1644 GNUNET_SERVICE_client_continue (client->client);
1649 * Main function that will be run
1651 * @param cls closure
1652 * @param c the configuration used
1653 * @param server the service handle
1657 const struct GNUNET_CONFIGURATION_Handle *c,
1658 struct GNUNET_SERVICE_Handle *server)
1662 if (GNUNET_OK != RECLAIM_TICKETS_init (cfg))
1664 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1665 "Unable to initialize TICKETS subsystem.\n");
1666 GNUNET_SCHEDULER_shutdown ();
1669 // Connect to identity and namestore services
1670 nsh = GNUNET_NAMESTORE_connect (cfg);
1673 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
1674 "error connecting to namestore");
1677 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
1682 * Called whenever a client is disconnected.
1684 * @param cls closure
1685 * @param client identification of the client
1686 * @param app_ctx @a client
1689 client_disconnect_cb (void *cls,
1690 struct GNUNET_SERVICE_Client *client,
1693 struct IdpClient *idp = app_ctx;
1695 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client);
1696 GNUNET_CONTAINER_DLL_remove (client_list_head,
1699 cleanup_client (idp);
1704 * Add a client to our list of active clients.
1707 * @param client client to add
1708 * @param mq message queue for @a client
1709 * @return internal namestore client structure for this client
1712 client_connect_cb (void *cls,
1713 struct GNUNET_SERVICE_Client *client,
1714 struct GNUNET_MQ_Handle *mq)
1716 struct IdpClient *idp;
1718 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
1719 idp = GNUNET_new (struct IdpClient);
1720 idp->client = client;
1722 GNUNET_CONTAINER_DLL_insert (client_list_head,
1730 * Define "main" method using service macro.
1732 GNUNET_SERVICE_MAIN (
1734 GNUNET_SERVICE_OPTION_NONE,
1737 &client_disconnect_cb,
1739 GNUNET_MQ_hd_var_size (attribute_store_message,
1740 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE,
1741 struct AttributeStoreMessage,
1743 GNUNET_MQ_hd_var_size (attribute_delete_message,
1744 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_DELETE,
1745 struct AttributeDeleteMessage,
1747 GNUNET_MQ_hd_fixed_size (
1749 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_START,
1750 struct AttributeIterationStartMessage,
1752 GNUNET_MQ_hd_fixed_size (iteration_next,
1753 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT,
1754 struct AttributeIterationNextMessage,
1756 GNUNET_MQ_hd_fixed_size (iteration_stop,
1757 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP,
1758 struct AttributeIterationStopMessage,
1760 GNUNET_MQ_hd_var_size (issue_ticket_message,
1761 GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET,
1762 struct IssueTicketMessage,
1764 GNUNET_MQ_hd_var_size (consume_ticket_message,
1765 GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET,
1766 struct ConsumeTicketMessage,
1768 GNUNET_MQ_hd_fixed_size (ticket_iteration_start,
1769 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_START,
1770 struct TicketIterationStartMessage,
1772 GNUNET_MQ_hd_fixed_size (ticket_iteration_next,
1773 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_NEXT,
1774 struct TicketIterationNextMessage,
1776 GNUNET_MQ_hd_fixed_size (ticket_iteration_stop,
1777 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_STOP,
1778 struct TicketIterationStopMessage,
1780 GNUNET_MQ_hd_var_size (revoke_ticket_message,
1781 GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET,
1782 struct RevokeTicketMessage,
1784 GNUNET_MQ_handler_end ());
1785 /* end of gnunet-service-reclaim.c */