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;
453 if (NULL != adh->ns_it)
454 GNUNET_NAMESTORE_zone_iteration_stop (adh->ns_it);
455 if (NULL != adh->ns_qe)
456 GNUNET_NAMESTORE_cancel (adh->ns_qe);
457 if (NULL != adh->label)
458 GNUNET_free (adh->label);
459 if (NULL != adh->claim)
460 GNUNET_free (adh->claim);
461 while (NULL != (le = adh->tickets_to_update_head)) {
462 GNUNET_CONTAINER_DLL_remove (adh->tickets_to_update_head,
463 adh->tickets_to_update_tail,
465 if (NULL != le->label)
466 GNUNET_free (le->label);
467 if (NULL != le->data)
468 GNUNET_free (le->data);
476 * Cleanup attribute store handle
478 * @param handle handle to clean up
481 cleanup_as_handle (struct AttributeStoreHandle *ash)
483 if (NULL != ash->ns_qe)
484 GNUNET_NAMESTORE_cancel (ash->ns_qe);
485 if (NULL != ash->claim)
486 GNUNET_free (ash->claim);
494 * @param idp the client to clean up
497 cleanup_client (struct IdpClient *idp)
499 struct AttributeIterator *ai;
500 struct TicketIteration *ti;
501 struct TicketRevocationOperation *rop;
502 struct TicketIssueOperation *iss;
503 struct ConsumeTicketOperation *ct;
504 struct AttributeStoreHandle *as;
505 struct AttributeDeleteHandle *adh;
507 while (NULL != (iss = idp->issue_op_head)) {
508 GNUNET_CONTAINER_DLL_remove (idp->issue_op_head, idp->issue_op_tail, iss);
511 while (NULL != (ct = idp->consume_op_head)) {
512 GNUNET_CONTAINER_DLL_remove (idp->consume_op_head,
513 idp->consume_op_tail,
516 RECLAIM_TICKETS_consume_cancel (ct->ch);
519 while (NULL != (as = idp->store_op_head)) {
520 GNUNET_CONTAINER_DLL_remove (idp->store_op_head, idp->store_op_tail, as);
521 cleanup_as_handle (as);
523 while (NULL != (adh = idp->delete_op_head)) {
524 GNUNET_CONTAINER_DLL_remove (idp->delete_op_head, idp->delete_op_tail, adh);
528 while (NULL != (ai = idp->attr_iter_head)) {
529 GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, idp->attr_iter_tail, ai);
532 while (NULL != (rop = idp->revoke_op_head)) {
533 GNUNET_CONTAINER_DLL_remove (idp->revoke_op_head, idp->revoke_op_tail, rop);
535 RECLAIM_TICKETS_revoke_cancel (rop->rh);
538 while (NULL != (ti = idp->ticket_iter_head)) {
539 GNUNET_CONTAINER_DLL_remove (idp->ticket_iter_head,
540 idp->ticket_iter_tail,
542 if (NULL != ti->iter)
543 RECLAIM_TICKETS_iteration_stop (ti->iter);
556 struct IdpClient *cl;
557 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
559 while (NULL != (cl = client_list_head))
561 GNUNET_CONTAINER_DLL_remove (client_list_head,
566 RECLAIM_TICKETS_deinit ();
567 if (NULL != timeout_task)
568 GNUNET_SCHEDULER_cancel (timeout_task);
570 GNUNET_NAMESTORE_disconnect (nsh);
580 do_shutdown (void *cls)
582 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down...\n");
588 * Sends a ticket result message to the client
590 * @param client the client to send to
591 * @param r_id the request message ID to reply to
592 * @param ticket the ticket to include (may be NULL)
593 * @param success the success status of the request
596 send_ticket_result (const struct IdpClient *client,
598 const struct GNUNET_RECLAIM_Ticket *ticket,
601 struct TicketResultMessage *irm;
602 struct GNUNET_MQ_Envelope *env;
604 env = GNUNET_MQ_msg (irm,
605 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
606 if (NULL != ticket) {
607 irm->ticket = *ticket;
609 // TODO add success member
610 irm->id = htonl (r_id);
611 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending TICKET_RESULT message\n");
612 GNUNET_MQ_send (client->mq, env);
617 * Issue ticket result
619 * @param cls out ticket issue operation handle
620 * @param ticket the issued ticket
621 * @param success issue success status (GNUNET_OK if successful)
622 * @param emsg error message (NULL of success is GNUNET_OK)
625 issue_ticket_result_cb (void *cls,
626 struct GNUNET_RECLAIM_Ticket *ticket,
630 struct TicketIssueOperation *tio = cls;
631 if (GNUNET_OK != success) {
632 send_ticket_result (tio->client, tio->r_id, NULL, GNUNET_SYSERR);
633 GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head,
634 tio->client->issue_op_tail,
637 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error issuing ticket: %s\n", emsg);
640 send_ticket_result (tio->client, tio->r_id, ticket, GNUNET_SYSERR);
641 GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head,
642 tio->client->issue_op_tail,
649 * Check issue ticket message
652 * @im message to check
653 * @return GNUNET_OK if message is ok
656 check_issue_ticket_message (void *cls, const struct IssueTicketMessage *im)
660 size = ntohs (im->header.size);
661 if (size <= sizeof (struct IssueTicketMessage)) {
663 return GNUNET_SYSERR;
670 * Handle ticket issue message
672 * @param cls our client
673 * @param im the message
676 handle_issue_ticket_message (void *cls, const struct IssueTicketMessage *im)
678 struct TicketIssueOperation *tio;
679 struct IdpClient *idp = cls;
680 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
683 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ISSUE_TICKET message\n");
684 tio = GNUNET_new (struct TicketIssueOperation);
685 attrs_len = ntohs (im->attr_len);
686 attrs = GNUNET_RECLAIM_ATTRIBUTE_list_deserialize ((char *)&im[1], attrs_len);
687 tio->r_id = ntohl (im->id);
689 GNUNET_CONTAINER_DLL_insert (idp->issue_op_head, idp->issue_op_tail, tio);
690 RECLAIM_TICKETS_issue (&im->identity,
693 &issue_ticket_result_cb,
695 GNUNET_SERVICE_client_continue (idp->client);
696 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (attrs);
701 /**********************************************************
703 **********************************************************/
706 * Handles revocation result
708 * @param cls our revocation operation handle
709 * @param success revocation result (GNUNET_OK if successful)
712 revoke_result_cb (void *cls, int32_t success)
714 struct TicketRevocationOperation *rop = cls;
715 struct GNUNET_MQ_Envelope *env;
716 struct RevokeTicketResultMessage *trm;
718 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending REVOKE_TICKET_RESULT message\n");
720 env = GNUNET_MQ_msg (trm, GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT);
721 trm->id = htonl (rop->r_id);
722 trm->success = htonl (success);
723 GNUNET_MQ_send (rop->client->mq, env);
724 GNUNET_CONTAINER_DLL_remove (rop->client->revoke_op_head,
725 rop->client->revoke_op_tail,
732 * Check revocation message format
735 * @param im the message to check
736 * @return GNUNET_OK if message is ok
739 check_revoke_ticket_message (void *cls, const struct RevokeTicketMessage *im)
743 size = ntohs (im->header.size);
744 if (size != sizeof (struct RevokeTicketMessage)) {
746 return GNUNET_SYSERR;
753 * Handle a revocation message to a ticket.
755 * @param cls our client
756 * @param rm the message to handle
759 handle_revoke_ticket_message (void *cls, const struct RevokeTicketMessage *rm)
761 struct TicketRevocationOperation *rop;
762 struct IdpClient *idp = cls;
764 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received REVOKE_TICKET message\n");
765 rop = GNUNET_new (struct TicketRevocationOperation);
766 rop->r_id = ntohl (rm->id);
768 GNUNET_CONTAINER_DLL_insert (idp->revoke_op_head, idp->revoke_op_tail, rop);
770 = RECLAIM_TICKETS_revoke (&rm->ticket, &rm->identity, &revoke_result_cb, rop);
771 GNUNET_SERVICE_client_continue (idp->client);
776 * Handle a ticket consume result
778 * @param cls our consume ticket operation handle
779 * @param identity the attribute authority
780 * @param attrs the attribute/claim list
781 * @param success GNUNET_OK if successful
782 * @param emsg error message (NULL if success=GNUNET_OK)
785 consume_result_cb (void *cls,
786 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
787 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
791 struct ConsumeTicketOperation *cop = cls;
792 struct ConsumeTicketResultMessage *crm;
793 struct GNUNET_MQ_Envelope *env;
796 if (GNUNET_OK != success) {
797 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error consuming ticket: %s\n", emsg);
799 attrs_len = GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (attrs);
800 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending CONSUME_TICKET_RESULT message\n");
801 env = GNUNET_MQ_msg_extra (crm,
803 GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT);
804 crm->id = htonl (cop->r_id);
805 crm->attrs_len = htons (attrs_len);
806 crm->identity = *identity;
807 crm->result = htonl (success);
808 data_tmp = (char *)&crm[1];
809 GNUNET_RECLAIM_ATTRIBUTE_list_serialize (attrs, data_tmp);
810 GNUNET_MQ_send (cop->client->mq, env);
811 GNUNET_CONTAINER_DLL_remove (cop->client->consume_op_head,
812 cop->client->consume_op_tail,
819 * Check a consume ticket message
822 * @param cm the message to handle
825 check_consume_ticket_message (void *cls, const struct ConsumeTicketMessage *cm)
829 size = ntohs (cm->header.size);
830 if (size != sizeof (struct ConsumeTicketMessage)) {
832 return GNUNET_SYSERR;
839 * Handle a consume ticket message
841 * @param cls our client handle
842 * @cm the message to handle
845 handle_consume_ticket_message (void *cls, const struct ConsumeTicketMessage *cm)
847 struct ConsumeTicketOperation *cop;
848 struct IdpClient *idp = cls;
850 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received CONSUME_TICKET message\n");
851 cop = GNUNET_new (struct ConsumeTicketOperation);
852 cop->r_id = ntohl (cm->id);
855 = RECLAIM_TICKETS_consume (&cm->identity, &cm->ticket, &consume_result_cb, cop);
856 GNUNET_CONTAINER_DLL_insert (idp->consume_op_head, idp->consume_op_tail, cop);
857 GNUNET_SERVICE_client_continue (idp->client);
860 /*****************************************
862 *****************************************/
866 * Attribute store result handler
868 * @param cls our attribute store handle
869 * @param success GNUNET_OK if successful
870 * @param emsg error message (NULL if success=GNUNET_OK)
873 attr_store_cont (void *cls, int32_t success, const char *emsg)
875 struct AttributeStoreHandle *ash = cls;
876 struct GNUNET_MQ_Envelope *env;
877 struct SuccessResultMessage *acr_msg;
880 GNUNET_CONTAINER_DLL_remove (ash->client->store_op_head,
881 ash->client->store_op_tail,
884 if (GNUNET_SYSERR == success) {
885 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
886 "Failed to store attribute %s\n",
888 cleanup_as_handle (ash);
889 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
893 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
894 env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
895 acr_msg->id = htonl (ash->r_id);
896 acr_msg->op_result = htonl (GNUNET_OK);
897 GNUNET_MQ_send (ash->client->mq, env);
898 cleanup_as_handle (ash);
903 * Add a new attribute
905 * @param cls the AttributeStoreHandle
908 attr_store_task (void *cls)
910 struct AttributeStoreHandle *ash = cls;
911 struct GNUNET_GNSRECORD_Data rd[1];
916 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Storing attribute\n");
917 buf_size = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (ash->claim);
918 buf = GNUNET_malloc (buf_size);
919 // Give the ash a new id if unset
920 if (0 == ash->claim->id)
922 = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX);
923 GNUNET_RECLAIM_ATTRIBUTE_serialize (ash->claim, buf);
925 = GNUNET_STRINGS_data_to_string_alloc (&ash->claim->id, sizeof (uint64_t));
926 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting with label %s\n", label);
928 rd[0].data_size = buf_size;
930 rd[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR;
931 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
932 rd[0].expiration_time = ash->exp.rel_value_us;
933 ash->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
946 * Check an attribute store message
949 * @param sam the message to check
952 check_attribute_store_message (void *cls,
953 const struct AttributeStoreMessage *sam)
957 size = ntohs (sam->header.size);
958 if (size <= sizeof (struct AttributeStoreMessage)) {
960 return GNUNET_SYSERR;
967 * Handle an attribute store message
969 * @param cls our client
970 * @param sam the message to handle
973 handle_attribute_store_message (void *cls,
974 const struct AttributeStoreMessage *sam)
976 struct AttributeStoreHandle *ash;
977 struct IdpClient *idp = cls;
979 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTRIBUTE_STORE message\n");
981 data_len = ntohs (sam->attr_len);
983 ash = GNUNET_new (struct AttributeStoreHandle);
984 ash->claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize ((char *)&sam[1], data_len);
986 ash->r_id = ntohl (sam->id);
987 ash->identity = sam->identity;
988 ash->exp.rel_value_us = GNUNET_ntohll (sam->exp);
989 GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity, &ash->identity_pkey);
991 GNUNET_SERVICE_client_continue (idp->client);
993 GNUNET_CONTAINER_DLL_insert (idp->store_op_head, idp->store_op_tail, ash);
994 GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
999 * Send a deletion success response
1001 * @param adh our attribute deletion handle
1002 * @param success the success status
1005 send_delete_response (struct AttributeDeleteHandle *adh, int32_t success)
1007 struct GNUNET_MQ_Envelope *env;
1008 struct SuccessResultMessage *acr_msg;
1010 GNUNET_CONTAINER_DLL_remove (adh->client->delete_op_head,
1011 adh->client->delete_op_tail,
1014 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
1015 env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
1016 acr_msg->id = htonl (adh->r_id);
1017 acr_msg->op_result = htonl (success);
1018 GNUNET_MQ_send (adh->client->mq, env);
1023 * Namestore iteration within attribute deletion.
1024 * We need to reissue tickets with the deleted attribute removed.
1026 * @param cls our attribute deletion handle
1027 * @param zone the private key of the ticket issuer
1028 * @param label the label of the record
1029 * @param rd_count number of records
1030 * @param rd record data
1033 ticket_iter (void *cls,
1034 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1036 unsigned int rd_count,
1037 const struct GNUNET_GNSRECORD_Data *rd)
1039 struct AttributeDeleteHandle *adh = cls;
1040 struct TicketRecordsEntry *le;
1041 int has_changed = GNUNET_NO;
1043 for (int i = 0; i < rd_count; i++) {
1044 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF != rd[i].record_type)
1046 if (0 != memcmp (rd[i].data, &adh->claim->id, sizeof (uint64_t)))
1048 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1049 "Attribute to delete found (%s)\n",
1051 has_changed = GNUNET_YES;
1054 if (GNUNET_YES == has_changed) {
1055 le = GNUNET_new (struct TicketRecordsEntry);
1056 le->data_size = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
1057 le->data = GNUNET_malloc (le->data_size);
1058 le->rd_count = rd_count;
1059 le->label = GNUNET_strdup (label);
1060 GNUNET_GNSRECORD_records_serialize (rd_count, rd, le->data_size, le->data);
1061 GNUNET_CONTAINER_DLL_insert (adh->tickets_to_update_head,
1062 adh->tickets_to_update_tail,
1065 GNUNET_NAMESTORE_zone_iterator_next (adh->ns_it, 1);
1070 * Recursion prototype for function
1071 * @param cls our deletion handle
1074 update_tickets (void *cls);
1078 * Callback called when a ticket was updated
1080 * @param cls our attribute deletion handle
1081 * @param success GNUNET_OK if successful
1082 * @param emsg error message (NULL if success=GNUNET_OK)
1085 ticket_updated (void *cls, int32_t success, const char *emsg)
1087 struct AttributeDeleteHandle *adh = cls;
1089 GNUNET_SCHEDULER_add_now (&update_tickets, adh);
1094 * Update tickets: Remove shared attribute which has just been deleted.
1095 * This method is called recursively until all tickets are processed.
1096 * Eventually, the updated tickets are stored using ``update_tickets''.
1098 * @param cls our attribute deletion handle
1101 update_tickets (void *cls)
1103 struct AttributeDeleteHandle *adh = cls;
1104 struct TicketRecordsEntry *le;
1105 if (NULL == adh->tickets_to_update_head) {
1106 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1107 "Finished updatding tickets, success\n");
1108 send_delete_response (adh, GNUNET_OK);
1112 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1114 adh->tickets_to_update_head->label);
1115 le = adh->tickets_to_update_head;
1116 GNUNET_CONTAINER_DLL_remove (adh->tickets_to_update_head,
1117 adh->tickets_to_update_tail,
1119 struct GNUNET_GNSRECORD_Data rd[le->rd_count];
1120 struct GNUNET_GNSRECORD_Data rd_new[le->rd_count - 1];
1121 if (GNUNET_OK != GNUNET_GNSRECORD_records_deserialize (le->data_size,
1126 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1127 "Unable to deserialize record data!\n");
1128 send_delete_response (adh, GNUNET_SYSERR);
1133 for (int i = 0; i < le->rd_count; i++) {
1134 if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF == rd[i].record_type)
1135 && (0 == memcmp (rd[i].data, &adh->claim->id, sizeof (uint64_t))))
1140 adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1147 GNUNET_free (le->label);
1148 GNUNET_free (le->data);
1154 * Done collecting affected tickets, start updating.
1156 * @param cls our attribute deletion handle
1159 ticket_iter_fin (void *cls)
1161 struct AttributeDeleteHandle *adh = cls;
1163 GNUNET_SCHEDULER_add_now (&update_tickets, adh);
1168 * Error collecting affected tickets. Abort.
1170 * @param cls our attribute deletion handle
1173 ticket_iter_err (void *cls)
1175 struct AttributeDeleteHandle *adh = cls;
1177 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1178 "Namestore error on delete %s\n",
1180 send_delete_response (adh, GNUNET_SYSERR);
1186 * Start processing tickets which may still contain reference to deleted
1189 * @param cls attribute deletion handle
1192 start_ticket_update (void *cls)
1194 struct AttributeDeleteHandle *adh = cls;
1195 adh->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh,
1207 * Attribute deleted callback
1209 * @param cls our handle
1210 * @param success success status
1211 * @param emsg error message (NULL if success=GNUNET_OK)
1214 attr_delete_cont (void *cls, int32_t success, const char *emsg)
1216 struct AttributeDeleteHandle *adh = cls;
1218 if (GNUNET_SYSERR == success) {
1219 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1220 "Error deleting attribute %s\n",
1222 send_delete_response (adh, GNUNET_SYSERR);
1226 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating tickets...\n");
1227 GNUNET_SCHEDULER_add_now (&start_ticket_update, adh);
1232 * Check attribute delete message format
1235 * @dam message to check
1238 check_attribute_delete_message (void *cls,
1239 const struct AttributeDeleteMessage *dam)
1243 size = ntohs (dam->header.size);
1244 if (size <= sizeof (struct AttributeDeleteMessage)) {
1246 return GNUNET_SYSERR;
1253 * Handle attribute deletion
1255 * @param cls our client
1256 * @param dam deletion message
1259 handle_attribute_delete_message (void *cls,
1260 const struct AttributeDeleteMessage *dam)
1262 struct AttributeDeleteHandle *adh;
1263 struct IdpClient *idp = cls;
1265 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTRIBUTE_DELETE message\n");
1267 data_len = ntohs (dam->attr_len);
1269 adh = GNUNET_new (struct AttributeDeleteHandle);
1270 adh->claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize ((char *)&dam[1], data_len);
1272 adh->r_id = ntohl (dam->id);
1273 adh->identity = dam->identity;
1275 = GNUNET_STRINGS_data_to_string_alloc (&adh->claim->id, sizeof (uint64_t));
1276 GNUNET_SERVICE_client_continue (idp->client);
1278 GNUNET_CONTAINER_DLL_insert (idp->delete_op_head, idp->delete_op_tail, adh);
1279 adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1289 /*************************************************
1290 * Attrubute iteration
1291 *************************************************/
1295 * Done iterating over attributes
1297 * @param cls our iterator handle
1300 attr_iter_finished (void *cls)
1302 struct AttributeIterator *ai = cls;
1303 struct GNUNET_MQ_Envelope *env;
1304 struct AttributeResultMessage *arm;
1306 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending ATTRIBUTE_RESULT message\n");
1307 env = GNUNET_MQ_msg (arm, GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
1308 arm->id = htonl (ai->request_id);
1309 arm->attr_len = htons (0);
1310 GNUNET_MQ_send (ai->client->mq, env);
1311 GNUNET_CONTAINER_DLL_remove (ai->client->attr_iter_head,
1312 ai->client->attr_iter_tail,
1318 * Error iterating over attributes. Abort.
1320 * @param cls our attribute iteration handle
1323 attr_iter_error (void *cls)
1325 struct AttributeIterator *ai = cls;
1327 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to iterate over attributes\n");
1328 attr_iter_finished (ai);
1333 * Got record. Return if it is an attribute.
1335 * @param cls our attribute iterator
1336 * @param zone zone we are iterating
1337 * @param label label of the records
1338 * @param rd_count record count
1342 attr_iter_cb (void *cls,
1343 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1345 unsigned int rd_count,
1346 const struct GNUNET_GNSRECORD_Data *rd)
1348 struct AttributeIterator *ai = cls;
1349 struct AttributeResultMessage *arm;
1350 struct GNUNET_MQ_Envelope *env;
1353 if (rd_count != 1) {
1354 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1358 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR != rd->record_type) {
1359 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1362 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found attribute under: %s\n", label);
1363 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending ATTRIBUTE_RESULT message\n");
1364 env = GNUNET_MQ_msg_extra (arm,
1366 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
1367 arm->id = htonl (ai->request_id);
1368 arm->attr_len = htons (rd->data_size);
1369 GNUNET_CRYPTO_ecdsa_key_get_public (zone, &arm->identity);
1370 data_tmp = (char *)&arm[1];
1371 GNUNET_memcpy (data_tmp, rd->data, rd->data_size);
1372 GNUNET_MQ_send (ai->client->mq, env);
1377 * Iterate over zone to get attributes
1379 * @param cls our client
1380 * @param ais_msg the iteration message to start
1383 handle_iteration_start (void *cls,
1384 const struct AttributeIterationStartMessage *ais_msg)
1386 struct IdpClient *idp = cls;
1387 struct AttributeIterator *ai;
1389 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1390 "Received ATTRIBUTE_ITERATION_START message\n");
1391 ai = GNUNET_new (struct AttributeIterator);
1392 ai->request_id = ntohl (ais_msg->id);
1394 ai->identity = ais_msg->identity;
1396 GNUNET_CONTAINER_DLL_insert (idp->attr_iter_head, idp->attr_iter_tail, ai);
1397 ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh,
1403 &attr_iter_finished,
1405 GNUNET_SERVICE_client_continue (idp->client);
1410 * Handle iteration stop message from client
1412 * @param cls the client
1413 * @param ais_msg the stop message
1416 handle_iteration_stop (void *cls,
1417 const struct AttributeIterationStopMessage *ais_msg)
1419 struct IdpClient *idp = cls;
1420 struct AttributeIterator *ai;
1423 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1424 "Received `%s' message\n",
1425 "ATTRIBUTE_ITERATION_STOP");
1426 rid = ntohl (ais_msg->id);
1427 for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
1428 if (ai->request_id == rid)
1432 GNUNET_SERVICE_client_drop (idp->client);
1435 GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, idp->attr_iter_tail, ai);
1437 GNUNET_SERVICE_client_continue (idp->client);
1442 * Client requests next attribute from iterator
1444 * @param cls the client
1445 * @param ais_msg the message
1448 handle_iteration_next (void *cls,
1449 const struct AttributeIterationNextMessage *ais_msg)
1451 struct IdpClient *idp = cls;
1452 struct AttributeIterator *ai;
1455 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1456 "Received ATTRIBUTE_ITERATION_NEXT message\n");
1457 rid = ntohl (ais_msg->id);
1458 for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
1459 if (ai->request_id == rid)
1463 GNUNET_SERVICE_client_drop (idp->client);
1466 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1467 GNUNET_SERVICE_client_continue (idp->client);
1470 /******************************************************
1472 ******************************************************/
1475 * Got a ticket. Return to client
1477 * @param cls our ticket iterator
1478 * @param ticket the ticket
1481 ticket_iter_cb (void *cls, struct GNUNET_RECLAIM_Ticket *ticket)
1483 struct TicketIteration *ti = cls;
1484 struct GNUNET_MQ_Envelope *env;
1485 struct TicketResultMessage *trm;
1487 env = GNUNET_MQ_msg (trm, GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
1488 if (NULL == ticket) {
1489 /* send empty response to indicate end of list */
1490 GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head,
1491 ti->client->ticket_iter_tail,
1494 trm->ticket = *ticket;
1496 trm->id = htonl (ti->r_id);
1497 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending TICKET_RESULT message\n");
1498 GNUNET_MQ_send (ti->client->mq, env);
1505 * Client requests a ticket iteration
1507 * @param cls the client
1508 * @param tis_msg the iteration request message
1511 handle_ticket_iteration_start (
1513 const struct TicketIterationStartMessage *tis_msg)
1515 struct IdpClient *client = cls;
1516 struct TicketIteration *ti;
1518 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1519 "Received TICKET_ITERATION_START message\n");
1520 ti = GNUNET_new (struct TicketIteration);
1521 ti->r_id = ntohl (tis_msg->id);
1522 ti->client = client;
1524 GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
1525 client->ticket_iter_tail,
1528 = RECLAIM_TICKETS_iteration_start (&tis_msg->identity, &ticket_iter_cb, ti);
1529 GNUNET_SERVICE_client_continue (client->client);
1534 * Client has had enough tickets
1536 * @param cls the client
1537 * @param tis_msg the stop message
1540 handle_ticket_iteration_stop (void *cls,
1541 const struct TicketIterationStopMessage *tis_msg)
1543 struct IdpClient *client = cls;
1544 struct TicketIteration *ti;
1547 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1548 "Received `%s' message\n",
1549 "TICKET_ITERATION_STOP");
1550 rid = ntohl (tis_msg->id);
1551 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
1552 if (ti->r_id == rid)
1556 GNUNET_SERVICE_client_drop (client->client);
1559 RECLAIM_TICKETS_iteration_stop (ti->iter);
1560 GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
1561 client->ticket_iter_tail,
1564 GNUNET_SERVICE_client_continue (client->client);
1569 * Client requests next result.
1571 * @param cls the client
1572 * @param tis_msg the message
1575 handle_ticket_iteration_next (void *cls,
1576 const struct TicketIterationNextMessage *tis_msg)
1578 struct IdpClient *client = cls;
1579 struct TicketIteration *ti;
1582 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1583 "Received TICKET_ITERATION_NEXT message\n");
1584 rid = ntohl (tis_msg->id);
1585 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
1586 if (ti->r_id == rid)
1590 GNUNET_SERVICE_client_drop (client->client);
1593 RECLAIM_TICKETS_iteration_next (ti->iter);
1594 GNUNET_SERVICE_client_continue (client->client);
1599 * Main function that will be run
1601 * @param cls closure
1602 * @param c the configuration used
1603 * @param server the service handle
1607 const struct GNUNET_CONFIGURATION_Handle *c,
1608 struct GNUNET_SERVICE_Handle *server)
1612 if (GNUNET_OK != RECLAIM_TICKETS_init (cfg)) {
1613 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1614 "Unable to initialize TICKETS subsystem.\n");
1615 GNUNET_SCHEDULER_shutdown ();
1618 // Connect to identity and namestore services
1619 nsh = GNUNET_NAMESTORE_connect (cfg);
1621 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
1622 "error connecting to namestore");
1625 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
1630 * Called whenever a client is disconnected.
1632 * @param cls closure
1633 * @param client identification of the client
1634 * @param app_ctx @a client
1637 client_disconnect_cb (void *cls,
1638 struct GNUNET_SERVICE_Client *client,
1641 struct IdpClient *idp = app_ctx;
1642 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client);
1643 GNUNET_CONTAINER_DLL_remove (client_list_head,
1646 cleanup_client (idp);
1651 * Add a client to our list of active clients.
1654 * @param client client to add
1655 * @param mq message queue for @a client
1656 * @return internal namestore client structure for this client
1659 client_connect_cb (void *cls,
1660 struct GNUNET_SERVICE_Client *client,
1661 struct GNUNET_MQ_Handle *mq)
1663 struct IdpClient *idp;
1664 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
1665 idp = GNUNET_new (struct IdpClient);
1666 idp->client = client;
1668 GNUNET_CONTAINER_DLL_insert (client_list_head,
1676 * Define "main" method using service macro.
1678 GNUNET_SERVICE_MAIN (
1680 GNUNET_SERVICE_OPTION_NONE,
1683 &client_disconnect_cb,
1685 GNUNET_MQ_hd_var_size (attribute_store_message,
1686 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE,
1687 struct AttributeStoreMessage,
1689 GNUNET_MQ_hd_var_size (attribute_delete_message,
1690 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_DELETE,
1691 struct AttributeDeleteMessage,
1693 GNUNET_MQ_hd_fixed_size (
1695 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_START,
1696 struct AttributeIterationStartMessage,
1698 GNUNET_MQ_hd_fixed_size (iteration_next,
1699 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT,
1700 struct AttributeIterationNextMessage,
1702 GNUNET_MQ_hd_fixed_size (iteration_stop,
1703 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP,
1704 struct AttributeIterationStopMessage,
1706 GNUNET_MQ_hd_var_size (issue_ticket_message,
1707 GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET,
1708 struct IssueTicketMessage,
1710 GNUNET_MQ_hd_var_size (consume_ticket_message,
1711 GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET,
1712 struct ConsumeTicketMessage,
1714 GNUNET_MQ_hd_fixed_size (ticket_iteration_start,
1715 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_START,
1716 struct TicketIterationStartMessage,
1718 GNUNET_MQ_hd_fixed_size (ticket_iteration_next,
1719 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_NEXT,
1720 struct TicketIterationNextMessage,
1722 GNUNET_MQ_hd_fixed_size (ticket_iteration_stop,
1723 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_STOP,
1724 struct TicketIterationStopMessage,
1726 GNUNET_MQ_hd_var_size (revoke_ticket_message,
1727 GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET,
1728 struct RevokeTicketMessage,
1730 GNUNET_MQ_handler_end ());
1731 /* end of gnunet-service-reclaim.c */