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;
603 struct GNUNET_RECLAIM_Ticket *ticket_buf;
605 if (NULL != ticket) {
606 env = GNUNET_MQ_msg_extra (irm,
607 sizeof (struct GNUNET_RECLAIM_Ticket),
608 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
609 ticket_buf = (struct GNUNET_RECLAIM_Ticket *)&irm[1];
610 *ticket_buf = *ticket;
612 env = GNUNET_MQ_msg (irm, GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
614 // TODO add success member
615 irm->id = htonl (r_id);
616 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending TICKET_RESULT message\n");
617 GNUNET_MQ_send (client->mq, env);
622 * Issue ticket result
624 * @param cls out ticket issue operation handle
625 * @param ticket the issued ticket
626 * @param success issue success status (GNUNET_OK if successful)
627 * @param emsg error message (NULL of success is GNUNET_OK)
630 issue_ticket_result_cb (void *cls,
631 struct GNUNET_RECLAIM_Ticket *ticket,
635 struct TicketIssueOperation *tio = cls;
636 if (GNUNET_OK != success) {
637 send_ticket_result (tio->client, tio->r_id, NULL, GNUNET_SYSERR);
638 GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head,
639 tio->client->issue_op_tail,
642 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error issuing ticket: %s\n", emsg);
645 send_ticket_result (tio->client, tio->r_id, ticket, GNUNET_SYSERR);
646 GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head,
647 tio->client->issue_op_tail,
654 * Check issue ticket message
657 * @im message to check
658 * @return GNUNET_OK if message is ok
661 check_issue_ticket_message (void *cls, const struct IssueTicketMessage *im)
665 size = ntohs (im->header.size);
666 if (size <= sizeof (struct IssueTicketMessage)) {
668 return GNUNET_SYSERR;
675 * Handle ticket issue message
677 * @param cls our client
678 * @param im the message
681 handle_issue_ticket_message (void *cls, const struct IssueTicketMessage *im)
683 struct TicketIssueOperation *tio;
684 struct IdpClient *idp = cls;
685 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
688 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ISSUE_TICKET message\n");
689 tio = GNUNET_new (struct TicketIssueOperation);
690 attrs_len = ntohs (im->attr_len);
691 attrs = GNUNET_RECLAIM_ATTRIBUTE_list_deserialize ((char *)&im[1], attrs_len);
692 tio->r_id = ntohl (im->id);
694 GNUNET_CONTAINER_DLL_insert (idp->issue_op_head, idp->issue_op_tail, tio);
695 RECLAIM_TICKETS_issue (&im->identity,
698 &issue_ticket_result_cb,
700 GNUNET_SERVICE_client_continue (idp->client);
701 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (attrs);
706 /**********************************************************
708 **********************************************************/
711 * Handles revocation result
713 * @param cls our revocation operation handle
714 * @param success revocation result (GNUNET_OK if successful)
717 revoke_result_cb (void *cls, int32_t success)
719 struct TicketRevocationOperation *rop = cls;
720 struct GNUNET_MQ_Envelope *env;
721 struct RevokeTicketResultMessage *trm;
723 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending REVOKE_TICKET_RESULT message\n");
725 env = GNUNET_MQ_msg (trm, GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT);
726 trm->id = htonl (rop->r_id);
727 trm->success = htonl (success);
728 GNUNET_MQ_send (rop->client->mq, env);
729 GNUNET_CONTAINER_DLL_remove (rop->client->revoke_op_head,
730 rop->client->revoke_op_tail,
737 * Check revocation message format
740 * @param im the message to check
741 * @return GNUNET_OK if message is ok
744 check_revoke_ticket_message (void *cls, const struct RevokeTicketMessage *im)
748 size = ntohs (im->header.size);
749 if (size <= sizeof (struct RevokeTicketMessage)) {
751 return GNUNET_SYSERR;
758 * Handle a revocation message to a ticket.
760 * @param cls our client
761 * @param rm the message to handle
764 handle_revoke_ticket_message (void *cls, const struct RevokeTicketMessage *rm)
766 struct TicketRevocationOperation *rop;
767 struct IdpClient *idp = cls;
768 struct GNUNET_RECLAIM_Ticket *ticket;
770 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received REVOKE_TICKET message\n");
771 rop = GNUNET_new (struct TicketRevocationOperation);
772 ticket = (struct GNUNET_RECLAIM_Ticket *)&rm[1];
773 rop->r_id = ntohl (rm->id);
775 GNUNET_CONTAINER_DLL_insert (idp->revoke_op_head, idp->revoke_op_tail, rop);
777 = RECLAIM_TICKETS_revoke (ticket, &rm->identity, &revoke_result_cb, rop);
778 GNUNET_SERVICE_client_continue (idp->client);
783 * Handle a ticket consume result
785 * @param cls our consume ticket operation handle
786 * @param identity the attribute authority
787 * @param attrs the attribute/claim list
788 * @param success GNUNET_OK if successful
789 * @param emsg error message (NULL if success=GNUNET_OK)
792 consume_result_cb (void *cls,
793 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
794 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
798 struct ConsumeTicketOperation *cop = cls;
799 struct ConsumeTicketResultMessage *crm;
800 struct GNUNET_MQ_Envelope *env;
803 if (GNUNET_OK != success) {
804 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error consuming ticket: %s\n", emsg);
806 attrs_len = GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (attrs);
807 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending CONSUME_TICKET_RESULT message\n");
808 env = GNUNET_MQ_msg_extra (crm,
810 GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT);
811 crm->id = htonl (cop->r_id);
812 crm->attrs_len = htons (attrs_len);
813 crm->identity = *identity;
814 crm->result = htonl (success);
815 data_tmp = (char *)&crm[1];
816 GNUNET_RECLAIM_ATTRIBUTE_list_serialize (attrs, data_tmp);
817 GNUNET_MQ_send (cop->client->mq, env);
818 GNUNET_CONTAINER_DLL_remove (cop->client->consume_op_head,
819 cop->client->consume_op_tail,
826 * Check a consume ticket message
829 * @param cm the message to handle
832 check_consume_ticket_message (void *cls, const struct ConsumeTicketMessage *cm)
836 size = ntohs (cm->header.size);
837 if (size <= sizeof (struct ConsumeTicketMessage)) {
839 return GNUNET_SYSERR;
846 * Handle a consume ticket message
848 * @param cls our client handle
849 * @cm the message to handle
852 handle_consume_ticket_message (void *cls, const struct ConsumeTicketMessage *cm)
854 struct ConsumeTicketOperation *cop;
855 struct GNUNET_RECLAIM_Ticket *ticket;
856 struct IdpClient *idp = cls;
858 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received CONSUME_TICKET message\n");
859 cop = GNUNET_new (struct ConsumeTicketOperation);
860 cop->r_id = ntohl (cm->id);
862 ticket = (struct GNUNET_RECLAIM_Ticket *)&cm[1];
864 = RECLAIM_TICKETS_consume (&cm->identity, ticket, &consume_result_cb, cop);
865 GNUNET_CONTAINER_DLL_insert (idp->consume_op_head, idp->consume_op_tail, cop);
866 GNUNET_SERVICE_client_continue (idp->client);
869 /*****************************************
871 *****************************************/
875 * Attribute store result handler
877 * @param cls our attribute store handle
878 * @param success GNUNET_OK if successful
879 * @param emsg error message (NULL if success=GNUNET_OK)
882 attr_store_cont (void *cls, int32_t success, const char *emsg)
884 struct AttributeStoreHandle *ash = cls;
885 struct GNUNET_MQ_Envelope *env;
886 struct SuccessResultMessage *acr_msg;
889 GNUNET_CONTAINER_DLL_remove (ash->client->store_op_head,
890 ash->client->store_op_tail,
893 if (GNUNET_SYSERR == success) {
894 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
895 "Failed to store attribute %s\n",
897 cleanup_as_handle (ash);
898 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
902 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
903 env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
904 acr_msg->id = htonl (ash->r_id);
905 acr_msg->op_result = htonl (GNUNET_OK);
906 GNUNET_MQ_send (ash->client->mq, env);
907 cleanup_as_handle (ash);
912 * Add a new attribute
914 * @param cls the AttributeStoreHandle
917 attr_store_task (void *cls)
919 struct AttributeStoreHandle *ash = cls;
920 struct GNUNET_GNSRECORD_Data rd[1];
925 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Storing attribute\n");
926 buf_size = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (ash->claim);
927 buf = GNUNET_malloc (buf_size);
928 // Give the ash a new id if unset
929 if (0 == ash->claim->id)
931 = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX);
932 GNUNET_RECLAIM_ATTRIBUTE_serialize (ash->claim, buf);
934 = GNUNET_STRINGS_data_to_string_alloc (&ash->claim->id, sizeof (uint64_t));
935 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting with label %s\n", label);
937 rd[0].data_size = buf_size;
939 rd[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR;
940 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
941 rd[0].expiration_time = ash->exp.rel_value_us;
942 ash->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
954 * Check an attribute store message
957 * @param sam the message to check
960 check_attribute_store_message (void *cls,
961 const struct AttributeStoreMessage *sam)
965 size = ntohs (sam->header.size);
966 if (size <= sizeof (struct AttributeStoreMessage)) {
968 return GNUNET_SYSERR;
975 * Handle an attribute store message
977 * @param cls our client
978 * @param sam the message to handle
981 handle_attribute_store_message (void *cls,
982 const struct AttributeStoreMessage *sam)
984 struct AttributeStoreHandle *ash;
985 struct IdpClient *idp = cls;
987 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTRIBUTE_STORE message\n");
989 data_len = ntohs (sam->attr_len);
991 ash = GNUNET_new (struct AttributeStoreHandle);
992 ash->claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize ((char *)&sam[1], data_len);
994 ash->r_id = ntohl (sam->id);
995 ash->identity = sam->identity;
996 ash->exp.rel_value_us = GNUNET_ntohll (sam->exp);
997 GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity, &ash->identity_pkey);
999 GNUNET_SERVICE_client_continue (idp->client);
1001 GNUNET_CONTAINER_DLL_insert (idp->store_op_head, idp->store_op_tail, ash);
1002 GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
1007 * Send a deletion success response
1009 * @param adh our attribute deletion handle
1010 * @param success the success status
1013 send_delete_response (struct AttributeDeleteHandle *adh, int32_t success)
1015 struct GNUNET_MQ_Envelope *env;
1016 struct SuccessResultMessage *acr_msg;
1018 GNUNET_CONTAINER_DLL_remove (adh->client->delete_op_head,
1019 adh->client->delete_op_tail,
1022 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
1023 env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
1024 acr_msg->id = htonl (adh->r_id);
1025 acr_msg->op_result = htonl (success);
1026 GNUNET_MQ_send (adh->client->mq, env);
1031 * Namestore iteration within attribute deletion.
1032 * We need to reissue tickets with the deleted attribute removed.
1034 * @param cls our attribute deletion handle
1035 * @param zone the private key of the ticket issuer
1036 * @param label the label of the record
1037 * @param rd_count number of records
1038 * @param rd record data
1041 ticket_iter (void *cls,
1042 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1044 unsigned int rd_count,
1045 const struct GNUNET_GNSRECORD_Data *rd)
1047 struct AttributeDeleteHandle *adh = cls;
1048 struct TicketRecordsEntry *le;
1049 int has_changed = GNUNET_NO;
1051 for (int i = 0; i < rd_count; i++) {
1052 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF != rd[i].record_type)
1054 if (0 != memcmp (rd[i].data, &adh->claim->id, sizeof (uint64_t)))
1056 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1057 "Attribute to delete found (%s)\n",
1059 has_changed = GNUNET_YES;
1062 if (GNUNET_YES == has_changed) {
1063 le = GNUNET_new (struct TicketRecordsEntry);
1064 le->data_size = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
1065 le->data = GNUNET_malloc (le->data_size);
1066 le->rd_count = rd_count;
1067 le->label = GNUNET_strdup (label);
1068 GNUNET_GNSRECORD_records_serialize (rd_count, rd, le->data_size, le->data);
1069 GNUNET_CONTAINER_DLL_insert (adh->tickets_to_update_head,
1070 adh->tickets_to_update_tail,
1073 GNUNET_NAMESTORE_zone_iterator_next (adh->ns_it, 1);
1078 * Recursion prototype for function
1079 * @param cls our deletion handle
1082 update_tickets (void *cls);
1086 * Callback called when a ticket was updated
1088 * @param cls our attribute deletion handle
1089 * @param success GNUNET_OK if successful
1090 * @param emsg error message (NULL if success=GNUNET_OK)
1093 ticket_updated (void *cls, int32_t success, const char *emsg)
1095 struct AttributeDeleteHandle *adh = cls;
1097 GNUNET_SCHEDULER_add_now (&update_tickets, adh);
1102 * Update tickets: Remove shared attribute which has just been deleted.
1103 * This method is called recursively until all tickets are processed.
1104 * Eventually, the updated tickets are stored using ``update_tickets''.
1106 * @param cls our attribute deletion handle
1109 update_tickets (void *cls)
1111 struct AttributeDeleteHandle *adh = cls;
1112 struct TicketRecordsEntry *le;
1113 if (NULL == adh->tickets_to_update_head) {
1114 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1115 "Finished updatding tickets, success\n");
1116 send_delete_response (adh, GNUNET_OK);
1120 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1122 adh->tickets_to_update_head->label);
1123 le = adh->tickets_to_update_head;
1124 GNUNET_CONTAINER_DLL_remove (adh->tickets_to_update_head,
1125 adh->tickets_to_update_tail,
1127 struct GNUNET_GNSRECORD_Data rd[le->rd_count];
1128 struct GNUNET_GNSRECORD_Data rd_new[le->rd_count - 1];
1129 GNUNET_GNSRECORD_records_deserialize (le->data_size,
1134 for (int i = 0; i < le->rd_count; i++) {
1135 if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF == rd[i].record_type)
1136 && (0 == memcmp (rd[i].data, &adh->claim->id, sizeof (uint64_t))))
1141 adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1148 GNUNET_free (le->label);
1149 GNUNET_free (le->data);
1155 * Done collecting affected tickets, start updating.
1157 * @param cls our attribute deletion handle
1160 ticket_iter_fin (void *cls)
1162 struct AttributeDeleteHandle *adh = cls;
1164 GNUNET_SCHEDULER_add_now (&update_tickets, adh);
1169 * Error collecting affected tickets. Abort.
1171 * @param cls our attribute deletion handle
1174 ticket_iter_err (void *cls)
1176 struct AttributeDeleteHandle *adh = cls;
1178 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1179 "Namestore error on delete %s\n",
1181 send_delete_response (adh, GNUNET_SYSERR);
1187 * Start processing tickets which may still contain reference to deleted
1190 * @param cls attribute deletion handle
1193 start_ticket_update (void *cls)
1195 struct AttributeDeleteHandle *adh = cls;
1196 adh->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh,
1208 * Attribute deleted callback
1210 * @param cls our handle
1211 * @param success success status
1212 * @param emsg error message (NULL if success=GNUNET_OK)
1215 attr_delete_cont (void *cls, int32_t success, const char *emsg)
1217 struct AttributeDeleteHandle *adh = cls;
1219 if (GNUNET_SYSERR == success) {
1220 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1221 "Error deleting attribute %s\n",
1223 send_delete_response (adh, GNUNET_SYSERR);
1227 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating tickets...\n");
1228 GNUNET_SCHEDULER_add_now (&start_ticket_update, adh);
1233 * Check attribute delete message format
1236 * @dam message to check
1239 check_attribute_delete_message (void *cls,
1240 const struct AttributeDeleteMessage *dam)
1244 size = ntohs (dam->header.size);
1245 if (size <= sizeof (struct AttributeDeleteMessage)) {
1247 return GNUNET_SYSERR;
1254 * Handle attribute deletion
1256 * @param cls our client
1257 * @param dam deletion message
1260 handle_attribute_delete_message (void *cls,
1261 const struct AttributeDeleteMessage *dam)
1263 struct AttributeDeleteHandle *adh;
1264 struct IdpClient *idp = cls;
1266 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTRIBUTE_DELETE message\n");
1268 data_len = ntohs (dam->attr_len);
1270 adh = GNUNET_new (struct AttributeDeleteHandle);
1271 adh->claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize ((char *)&dam[1], data_len);
1273 adh->r_id = ntohl (dam->id);
1274 adh->identity = dam->identity;
1276 = GNUNET_STRINGS_data_to_string_alloc (&adh->claim->id, sizeof (uint64_t));
1277 GNUNET_SERVICE_client_continue (idp->client);
1279 GNUNET_CONTAINER_DLL_insert (idp->delete_op_head, idp->delete_op_tail, adh);
1280 adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1290 /*************************************************
1291 * Attrubute iteration
1292 *************************************************/
1296 * Done iterating over attributes
1298 * @param cls our iterator handle
1301 attr_iter_finished (void *cls)
1303 struct AttributeIterator *ai = cls;
1304 struct GNUNET_MQ_Envelope *env;
1305 struct AttributeResultMessage *arm;
1307 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending ATTRIBUTE_RESULT message\n");
1308 env = GNUNET_MQ_msg (arm, GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
1309 arm->id = htonl (ai->request_id);
1310 arm->attr_len = htons (0);
1311 GNUNET_MQ_send (ai->client->mq, env);
1312 GNUNET_CONTAINER_DLL_remove (ai->client->attr_iter_head,
1313 ai->client->attr_iter_tail,
1319 * Error iterating over attributes. Abort.
1321 * @param cls our attribute iteration handle
1324 attr_iter_error (void *cls)
1326 struct AttributeIterator *ai = cls;
1328 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to iterate over attributes\n");
1329 attr_iter_finished (ai);
1334 * Got record. Return if it is an attribute.
1336 * @param cls our attribute iterator
1337 * @param zone zone we are iterating
1338 * @param label label of the records
1339 * @param rd_count record count
1343 attr_iter_cb (void *cls,
1344 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1346 unsigned int rd_count,
1347 const struct GNUNET_GNSRECORD_Data *rd)
1349 struct AttributeIterator *ai = cls;
1350 struct AttributeResultMessage *arm;
1351 struct GNUNET_MQ_Envelope *env;
1354 if (rd_count != 1) {
1355 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1359 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR != rd->record_type) {
1360 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1363 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found attribute under: %s\n", label);
1364 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending ATTRIBUTE_RESULT message\n");
1365 env = GNUNET_MQ_msg_extra (arm,
1367 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
1368 arm->id = htonl (ai->request_id);
1369 arm->attr_len = htons (rd->data_size);
1370 GNUNET_CRYPTO_ecdsa_key_get_public (zone, &arm->identity);
1371 data_tmp = (char *)&arm[1];
1372 GNUNET_memcpy (data_tmp, rd->data, rd->data_size);
1373 GNUNET_MQ_send (ai->client->mq, env);
1378 * Iterate over zone to get attributes
1380 * @param cls our client
1381 * @param ais_msg the iteration message to start
1384 handle_iteration_start (void *cls,
1385 const struct AttributeIterationStartMessage *ais_msg)
1387 struct IdpClient *idp = cls;
1388 struct AttributeIterator *ai;
1390 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1391 "Received ATTRIBUTE_ITERATION_START message\n");
1392 ai = GNUNET_new (struct AttributeIterator);
1393 ai->request_id = ntohl (ais_msg->id);
1395 ai->identity = ais_msg->identity;
1397 GNUNET_CONTAINER_DLL_insert (idp->attr_iter_head, idp->attr_iter_tail, ai);
1398 ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh,
1404 &attr_iter_finished,
1406 GNUNET_SERVICE_client_continue (idp->client);
1411 * Handle iteration stop message from client
1413 * @param cls the client
1414 * @param ais_msg the stop message
1417 handle_iteration_stop (void *cls,
1418 const struct AttributeIterationStopMessage *ais_msg)
1420 struct IdpClient *idp = cls;
1421 struct AttributeIterator *ai;
1424 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1425 "Received `%s' message\n",
1426 "ATTRIBUTE_ITERATION_STOP");
1427 rid = ntohl (ais_msg->id);
1428 for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
1429 if (ai->request_id == rid)
1433 GNUNET_SERVICE_client_drop (idp->client);
1436 GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, idp->attr_iter_tail, ai);
1438 GNUNET_SERVICE_client_continue (idp->client);
1443 * Client requests next attribute from iterator
1445 * @param cls the client
1446 * @param ais_msg the message
1449 handle_iteration_next (void *cls,
1450 const struct AttributeIterationNextMessage *ais_msg)
1452 struct IdpClient *idp = cls;
1453 struct AttributeIterator *ai;
1456 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1457 "Received ATTRIBUTE_ITERATION_NEXT message\n");
1458 rid = ntohl (ais_msg->id);
1459 for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
1460 if (ai->request_id == rid)
1464 GNUNET_SERVICE_client_drop (idp->client);
1467 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1468 GNUNET_SERVICE_client_continue (idp->client);
1471 /******************************************************
1473 ******************************************************/
1476 * Got a ticket. Return to client
1478 * @param cls our ticket iterator
1479 * @param ticket the ticket
1482 ticket_iter_cb (void *cls, struct GNUNET_RECLAIM_Ticket *ticket)
1484 struct TicketIteration *ti = cls;
1485 struct GNUNET_MQ_Envelope *env;
1486 struct TicketResultMessage *trm;
1488 if (NULL == ticket) {
1489 /* send empty response to indicate end of list */
1490 env = GNUNET_MQ_msg (trm, GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
1491 GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head,
1492 ti->client->ticket_iter_tail,
1495 env = GNUNET_MQ_msg_extra (trm,
1496 sizeof (struct GNUNET_RECLAIM_Ticket),
1497 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
1498 memcpy (&trm[1], ticket, sizeof (struct GNUNET_RECLAIM_Ticket));
1500 trm->id = htonl (ti->r_id);
1501 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending TICKET_RESULT message\n");
1502 GNUNET_MQ_send (ti->client->mq, env);
1509 * Client requests a ticket iteration
1511 * @param cls the client
1512 * @param tis_msg the iteration request message
1515 handle_ticket_iteration_start (
1517 const struct TicketIterationStartMessage *tis_msg)
1519 struct IdpClient *client = cls;
1520 struct TicketIteration *ti;
1522 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1523 "Received TICKET_ITERATION_START message\n");
1524 ti = GNUNET_new (struct TicketIteration);
1525 ti->r_id = ntohl (tis_msg->id);
1526 ti->client = client;
1528 GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
1529 client->ticket_iter_tail,
1532 = RECLAIM_TICKETS_iteration_start (&tis_msg->identity, &ticket_iter_cb, ti);
1533 GNUNET_SERVICE_client_continue (client->client);
1538 * Client has had enough tickets
1540 * @param cls the client
1541 * @param tis_msg the stop message
1544 handle_ticket_iteration_stop (void *cls,
1545 const struct TicketIterationStopMessage *tis_msg)
1547 struct IdpClient *client = cls;
1548 struct TicketIteration *ti;
1551 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1552 "Received `%s' message\n",
1553 "TICKET_ITERATION_STOP");
1554 rid = ntohl (tis_msg->id);
1555 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
1556 if (ti->r_id == rid)
1560 GNUNET_SERVICE_client_drop (client->client);
1563 RECLAIM_TICKETS_iteration_stop (ti->iter);
1564 GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
1565 client->ticket_iter_tail,
1568 GNUNET_SERVICE_client_continue (client->client);
1573 * Client requests next result.
1575 * @param cls the client
1576 * @param tis_msg the message
1579 handle_ticket_iteration_next (void *cls,
1580 const struct TicketIterationNextMessage *tis_msg)
1582 struct IdpClient *client = cls;
1583 struct TicketIteration *ti;
1586 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1587 "Received TICKET_ITERATION_NEXT message\n");
1588 rid = ntohl (tis_msg->id);
1589 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
1590 if (ti->r_id == rid)
1594 GNUNET_SERVICE_client_drop (client->client);
1597 RECLAIM_TICKETS_iteration_next (ti->iter);
1598 GNUNET_SERVICE_client_continue (client->client);
1603 * Main function that will be run
1605 * @param cls closure
1606 * @param c the configuration used
1607 * @param server the service handle
1611 const struct GNUNET_CONFIGURATION_Handle *c,
1612 struct GNUNET_SERVICE_Handle *server)
1616 if (GNUNET_OK != RECLAIM_TICKETS_init (cfg)) {
1617 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1618 "Unable to initialize TICKETS subsystem.\n");
1619 GNUNET_SCHEDULER_shutdown ();
1622 // Connect to identity and namestore services
1623 nsh = GNUNET_NAMESTORE_connect (cfg);
1625 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
1626 "error connecting to namestore");
1629 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
1634 * Called whenever a client is disconnected.
1636 * @param cls closure
1637 * @param client identification of the client
1638 * @param app_ctx @a client
1641 client_disconnect_cb (void *cls,
1642 struct GNUNET_SERVICE_Client *client,
1645 struct IdpClient *idp = app_ctx;
1646 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client);
1647 GNUNET_CONTAINER_DLL_remove (client_list_head,
1650 cleanup_client (idp);
1655 * Add a client to our list of active clients.
1658 * @param client client to add
1659 * @param mq message queue for @a client
1660 * @return internal namestore client structure for this client
1663 client_connect_cb (void *cls,
1664 struct GNUNET_SERVICE_Client *client,
1665 struct GNUNET_MQ_Handle *mq)
1667 struct IdpClient *idp;
1668 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
1669 idp = GNUNET_new (struct IdpClient);
1670 idp->client = client;
1672 GNUNET_CONTAINER_DLL_insert (client_list_head,
1680 * Define "main" method using service macro.
1682 GNUNET_SERVICE_MAIN (
1684 GNUNET_SERVICE_OPTION_NONE,
1687 &client_disconnect_cb,
1689 GNUNET_MQ_hd_var_size (attribute_store_message,
1690 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE,
1691 struct AttributeStoreMessage,
1693 GNUNET_MQ_hd_var_size (attribute_delete_message,
1694 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_DELETE,
1695 struct AttributeDeleteMessage,
1697 GNUNET_MQ_hd_fixed_size (
1699 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_START,
1700 struct AttributeIterationStartMessage,
1702 GNUNET_MQ_hd_fixed_size (iteration_next,
1703 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT,
1704 struct AttributeIterationNextMessage,
1706 GNUNET_MQ_hd_fixed_size (iteration_stop,
1707 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP,
1708 struct AttributeIterationStopMessage,
1710 GNUNET_MQ_hd_var_size (issue_ticket_message,
1711 GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET,
1712 struct IssueTicketMessage,
1714 GNUNET_MQ_hd_var_size (consume_ticket_message,
1715 GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET,
1716 struct ConsumeTicketMessage,
1718 GNUNET_MQ_hd_fixed_size (ticket_iteration_start,
1719 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_START,
1720 struct TicketIterationStartMessage,
1722 GNUNET_MQ_hd_fixed_size (ticket_iteration_next,
1723 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_NEXT,
1724 struct TicketIterationNextMessage,
1726 GNUNET_MQ_hd_fixed_size (ticket_iteration_stop,
1727 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_STOP,
1728 struct TicketIterationStopMessage,
1730 GNUNET_MQ_hd_var_size (revoke_ticket_message,
1731 GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET,
1732 struct RevokeTicketMessage,
1734 GNUNET_MQ_handler_end ());
1735 /* end of gnunet-service-reclaim.c */