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
28 #include "gnunet_util_lib.h"
30 #include "gnunet-service-reclaim_tickets.h"
31 #include "gnunet_constants.h"
32 #include "gnunet_gnsrecord_lib.h"
33 #include "gnunet_identity_service.h"
34 #include "gnunet_namestore_service.h"
35 #include "gnunet_protocols.h"
36 #include "gnunet_reclaim_attribute_lib.h"
37 #include "gnunet_reclaim_service.h"
38 #include "gnunet_signatures.h"
47 * Normal operation state
49 #define STATE_POST_INIT 1
52 * Minimum interval between updates
54 #define MIN_WAIT_TIME GNUNET_TIME_UNIT_MINUTES
57 * Standard token expiration time
59 #define DEFAULT_TOKEN_EXPIRATION_INTERVAL GNUNET_TIME_UNIT_HOURS
64 static struct GNUNET_IDENTITY_Handle *identity_handle;
67 * Token expiration interval
69 static struct GNUNET_TIME_Relative token_expiration_interval;
74 static struct GNUNET_NAMESTORE_Handle *nsh;
79 static struct GNUNET_SCHEDULER_Task *timeout_task;
84 static struct GNUNET_SCHEDULER_Task *update_task;
89 static const struct GNUNET_CONFIGURATION_Handle *cfg;
97 * A ticket iteration operation.
99 struct TicketIteration
104 struct TicketIteration *next;
109 struct TicketIteration *prev;
112 * Client which intiated this zone iteration
114 struct IdpClient *client;
117 * The operation id fot the iteration in the response for the client
122 * The ticket iterator
124 struct RECLAIM_TICKETS_Iterator *iter;
128 * An attribute iteration operation.
130 struct AttributeIterator
133 * Next element in the DLL
135 struct AttributeIterator *next;
138 * Previous element in the DLL
140 struct AttributeIterator *prev;
143 * IDP client which intiated this zone iteration
145 struct IdpClient *client;
148 * Key of the zone we are iterating over.
150 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
155 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
158 * The operation id fot the zone iteration in the response for the client
172 struct GNUNET_SERVICE_Client *client;
175 * Message queue for transmission to @e client
177 struct GNUNET_MQ_Handle *mq;
181 * Attribute iteration operations in
182 * progress initiated by this client
184 struct AttributeIterator *attr_iter_head;
188 * Attribute iteration operations
189 * in progress initiated by this client
191 struct AttributeIterator *attr_iter_tail;
194 * Head of DLL of ticket iteration ops
196 struct TicketIteration *ticket_iter_head;
199 * Tail of DLL of ticket iteration ops
201 struct TicketIteration *ticket_iter_tail;
204 * Head of DLL of ticket revocation ops
206 struct TicketRevocationOperation *revoke_op_head;
209 * Tail of DLL of ticket revocation ops
211 struct TicketRevocationOperation *revoke_op_tail;
214 * Head of DLL of ticket issue ops
216 struct TicketIssueOperation *issue_op_head;
219 * Tail of DLL of ticket issue ops
221 struct TicketIssueOperation *issue_op_tail;
224 * Head of DLL of ticket consume ops
226 struct ConsumeTicketOperation *consume_op_head;
229 * Tail of DLL of ticket consume ops
231 struct ConsumeTicketOperation *consume_op_tail;
234 * Head of DLL of attribute store ops
236 struct AttributeStoreHandle *store_op_head;
239 * Tail of DLL of attribute store ops
241 struct AttributeStoreHandle *store_op_tail;
243 * Head of DLL of attribute delete ops
245 struct AttributeDeleteHandle *delete_op_head;
248 * Tail of DLL of attribute delete ops
250 struct AttributeDeleteHandle *delete_op_tail;
254 struct AttributeDeleteHandle
259 struct AttributeDeleteHandle *next;
264 struct AttributeDeleteHandle *prev;
269 struct IdpClient *client;
274 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
280 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
285 struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
288 * The attribute to delete
290 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
295 struct TicketRecordsEntry *tickets_to_update_head;
300 struct TicketRecordsEntry *tickets_to_update_tail;
314 struct AttributeStoreHandle
319 struct AttributeStoreHandle *next;
324 struct AttributeStoreHandle *prev;
329 struct IdpClient *client;
334 struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
339 struct GNUNET_CRYPTO_EcdsaPublicKey identity_pkey;
344 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
347 * The attribute to store
349 struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
352 * The attribute expiration interval
354 struct GNUNET_TIME_Relative exp;
362 struct ConsumeTicketOperation
367 struct ConsumeTicketOperation *next;
372 struct ConsumeTicketOperation *prev;
377 struct IdpClient *client;
385 * Ticket consume handle
387 struct RECLAIM_TICKETS_ConsumeHandle *ch;
391 * Updated attribute IDs
393 struct TicketAttributeUpdateEntry
398 struct TicketAttributeUpdateEntry *next;
403 struct TicketAttributeUpdateEntry *prev;
417 * Ticket revocation request handle
419 struct TicketRevocationOperation
424 struct TicketRevocationOperation *prev;
429 struct TicketRevocationOperation *next;
434 struct IdpClient *client;
439 struct RECLAIM_TICKETS_RevokeHandle *rh;
448 * Ticket issue operation handle
450 struct TicketIssueOperation
455 struct TicketIssueOperation *prev;
460 struct TicketIssueOperation *next;
465 struct IdpClient *client;
474 * DLL for ego handles to egos containing the RECLAIM_ATTRS in a
475 * map in json_t format
483 struct EgoEntry *next;
488 struct EgoEntry *prev;
493 struct GNUNET_IDENTITY_Ego *ego;
496 * Attribute map. Contains the attributes as json_t
498 struct GNUNET_CONTAINER_MultiHashMap *attr_map;
507 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
509 RECLAIM_TICKETS_deinit ();
510 if (NULL != timeout_task)
511 GNUNET_SCHEDULER_cancel (timeout_task);
512 if (NULL != update_task)
513 GNUNET_SCHEDULER_cancel (update_task);
514 if (NULL != identity_handle)
515 GNUNET_IDENTITY_disconnect (identity_handle);
517 GNUNET_NAMESTORE_disconnect (nsh);
526 do_shutdown (void *cls)
528 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down...\n");
534 send_ticket_result (const struct IdpClient *client, uint32_t r_id,
535 const struct GNUNET_RECLAIM_Ticket *ticket,
538 struct TicketResultMessage *irm;
539 struct GNUNET_MQ_Envelope *env;
540 struct GNUNET_RECLAIM_Ticket *ticket_buf;
542 if (NULL != ticket) {
543 env = GNUNET_MQ_msg_extra (irm, sizeof (struct GNUNET_RECLAIM_Ticket),
544 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
545 ticket_buf = (struct GNUNET_RECLAIM_Ticket *)&irm[1];
546 *ticket_buf = *ticket;
548 env = GNUNET_MQ_msg (irm, GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
550 // TODO add success member
551 irm->id = htonl (r_id);
552 GNUNET_MQ_send (client->mq, env);
556 issue_ticket_result_cb (void *cls, struct GNUNET_RECLAIM_Ticket *ticket,
557 int32_t success, const char *emsg)
559 struct TicketIssueOperation *tio = cls;
560 if (GNUNET_OK != success) {
561 send_ticket_result (tio->client, tio->r_id, NULL, GNUNET_SYSERR);
562 GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head,
563 tio->client->issue_op_tail, tio);
565 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error issuing ticket: %s\n", emsg);
568 send_ticket_result (tio->client, tio->r_id, ticket, GNUNET_SYSERR);
569 GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head,
570 tio->client->issue_op_tail, tio);
575 check_issue_ticket_message (void *cls, const struct IssueTicketMessage *im)
579 size = ntohs (im->header.size);
580 if (size <= sizeof (struct IssueTicketMessage)) {
582 return GNUNET_SYSERR;
588 handle_issue_ticket_message (void *cls, const struct IssueTicketMessage *im)
590 struct TicketIssueOperation *tio;
591 struct IdpClient *idp = cls;
592 struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
595 tio = GNUNET_new (struct TicketIssueOperation);
596 attrs_len = ntohs (im->attr_len);
597 attrs = GNUNET_RECLAIM_ATTRIBUTE_list_deserialize ((char *)&im[1], attrs_len);
598 tio->r_id = ntohl (im->id);
600 GNUNET_CONTAINER_DLL_insert (idp->issue_op_head, idp->issue_op_tail, tio);
601 RECLAIM_TICKETS_issue (&im->identity, attrs, &im->rp, &issue_ticket_result_cb,
603 GNUNET_SERVICE_client_continue (idp->client);
604 GNUNET_RECLAIM_ATTRIBUTE_list_destroy (attrs);
607 /**********************************************************
609 **********************************************************/
612 revoke_result_cb (void *cls, int32_t success)
614 struct TicketRevocationOperation *rop = cls;
615 struct GNUNET_MQ_Envelope *env;
616 struct RevokeTicketResultMessage *trm;
619 env = GNUNET_MQ_msg (trm, GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT);
620 trm->id = htonl (rop->r_id);
621 trm->success = htonl (success);
622 GNUNET_MQ_send (rop->client->mq, env);
623 GNUNET_CONTAINER_DLL_remove (rop->client->revoke_op_head,
624 rop->client->revoke_op_tail, rop);
630 check_revoke_ticket_message (void *cls, const struct RevokeTicketMessage *im)
634 size = ntohs (im->header.size);
635 if (size <= sizeof (struct RevokeTicketMessage)) {
637 return GNUNET_SYSERR;
643 handle_revoke_ticket_message (void *cls, const struct RevokeTicketMessage *rm)
645 struct TicketRevocationOperation *rop;
646 struct IdpClient *idp = cls;
647 struct GNUNET_RECLAIM_Ticket *ticket;
649 rop = GNUNET_new (struct TicketRevocationOperation);
650 ticket = (struct GNUNET_RECLAIM_Ticket *)&rm[1];
651 rop->r_id = ntohl (rm->id);
653 GNUNET_CONTAINER_DLL_insert (idp->revoke_op_head, idp->revoke_op_tail, rop);
655 RECLAIM_TICKETS_revoke (ticket, &rm->identity, &revoke_result_cb, rop);
656 GNUNET_SERVICE_client_continue (idp->client);
660 check_consume_ticket_message (void *cls, const struct ConsumeTicketMessage *cm)
664 size = ntohs (cm->header.size);
665 if (size <= sizeof (struct ConsumeTicketMessage)) {
667 return GNUNET_SYSERR;
673 consume_result_cb (void *cls,
674 const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
675 const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
676 int32_t success, const char *emsg)
678 struct ConsumeTicketOperation *cop = cls;
679 struct ConsumeTicketResultMessage *crm;
680 struct GNUNET_MQ_Envelope *env;
683 if (GNUNET_OK != success) {
684 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error consuming ticket: %s\n", emsg);
686 attrs_len = GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (attrs);
687 env = GNUNET_MQ_msg_extra (crm, attrs_len,
688 GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT);
689 crm->id = htonl (cop->r_id);
690 crm->attrs_len = htons (attrs_len);
691 crm->identity = *identity;
692 crm->result = htonl (success);
693 data_tmp = (char *)&crm[1];
694 GNUNET_RECLAIM_ATTRIBUTE_list_serialize (attrs, data_tmp);
695 GNUNET_MQ_send (cop->client->mq, env);
696 GNUNET_CONTAINER_DLL_remove (cop->client->consume_op_head,
697 cop->client->consume_op_tail, cop);
702 handle_consume_ticket_message (void *cls, const struct ConsumeTicketMessage *cm)
704 struct ConsumeTicketOperation *cop;
705 struct GNUNET_RECLAIM_Ticket *ticket;
706 struct IdpClient *idp = cls;
708 cop = GNUNET_new (struct ConsumeTicketOperation);
709 cop->r_id = ntohl (cm->id);
711 ticket = (struct GNUNET_RECLAIM_Ticket *)&cm[1];
713 RECLAIM_TICKETS_consume (&cm->identity, ticket, &consume_result_cb, cop);
714 GNUNET_CONTAINER_DLL_insert (idp->consume_op_head, idp->consume_op_tail, cop);
715 GNUNET_SERVICE_client_continue (idp->client);
718 /*****************************************
720 *****************************************/
723 * Cleanup attribute store handle
725 * @param handle handle to clean up
728 cleanup_as_handle (struct AttributeStoreHandle *ash)
730 if (NULL != ash->ns_qe)
731 GNUNET_NAMESTORE_cancel (ash->ns_qe);
732 if (NULL != ash->claim)
733 GNUNET_free (ash->claim);
738 attr_store_cont (void *cls, int32_t success, const char *emsg)
740 struct AttributeStoreHandle *ash = cls;
741 struct GNUNET_MQ_Envelope *env;
742 struct SuccessResultMessage *acr_msg;
745 GNUNET_CONTAINER_DLL_remove (ash->client->store_op_head,
746 ash->client->store_op_tail, ash);
748 if (GNUNET_SYSERR == success) {
749 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to store attribute %s\n",
751 cleanup_as_handle (ash);
752 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
756 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
757 env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
758 acr_msg->id = htonl (ash->r_id);
759 acr_msg->op_result = htonl (GNUNET_OK);
760 GNUNET_MQ_send (ash->client->mq, env);
761 cleanup_as_handle (ash);
765 * Adds a new attribute
767 * @param cls the AttributeStoreHandle
770 attr_store_task (void *cls)
772 struct AttributeStoreHandle *ash = cls;
773 struct GNUNET_GNSRECORD_Data rd[1];
778 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Storing attribute\n");
779 buf_size = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (ash->claim);
780 buf = GNUNET_malloc (buf_size);
781 // Give the ash a new id
783 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX);
784 GNUNET_RECLAIM_ATTRIBUTE_serialize (ash->claim, buf);
786 GNUNET_STRINGS_data_to_string_alloc (&ash->claim->id, sizeof (uint64_t));
787 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting with label %s\n", label);
789 rd[0].data_size = buf_size;
791 rd[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR;
792 rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
793 rd[0].expiration_time = ash->exp.rel_value_us;
794 ash->ns_qe = GNUNET_NAMESTORE_records_store (nsh, &ash->identity, label, 1,
795 rd, &attr_store_cont, ash);
800 check_attribute_store_message (void *cls,
801 const struct AttributeStoreMessage *sam)
805 size = ntohs (sam->header.size);
806 if (size <= sizeof (struct AttributeStoreMessage)) {
808 return GNUNET_SYSERR;
814 handle_attribute_store_message (void *cls,
815 const struct AttributeStoreMessage *sam)
817 struct AttributeStoreHandle *ash;
818 struct IdpClient *idp = cls;
820 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTRIBUTE_STORE message\n");
822 data_len = ntohs (sam->attr_len);
824 ash = GNUNET_new (struct AttributeStoreHandle);
825 ash->claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize ((char *)&sam[1], data_len);
827 ash->r_id = ntohl (sam->id);
828 ash->identity = sam->identity;
829 ash->exp.rel_value_us = GNUNET_ntohll (sam->exp);
830 GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity, &ash->identity_pkey);
832 GNUNET_SERVICE_client_continue (idp->client);
834 GNUNET_CONTAINER_DLL_insert (idp->store_op_head, idp->store_op_tail, ash);
835 GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
840 cleanup_adh (struct AttributeDeleteHandle *adh)
842 struct TicketRecordsEntry *le;
843 if (NULL != adh->ns_it)
844 GNUNET_NAMESTORE_zone_iteration_stop (adh->ns_it);
845 if (NULL != adh->ns_qe)
846 GNUNET_NAMESTORE_cancel (adh->ns_qe);
847 if (NULL != adh->label)
848 GNUNET_free (adh->label);
849 if (NULL != adh->claim)
850 GNUNET_free (adh->claim);
851 while (NULL != (le = adh->tickets_to_update_head)) {
852 GNUNET_CONTAINER_DLL_remove (adh->tickets_to_update_head,
853 adh->tickets_to_update_tail, le);
854 if (NULL != le->label)
855 GNUNET_free (le->label);
856 if (NULL != le->data)
857 GNUNET_free (le->data);
865 send_delete_response (struct AttributeDeleteHandle *adh, int32_t success)
867 struct GNUNET_MQ_Envelope *env;
868 struct SuccessResultMessage *acr_msg;
870 GNUNET_CONTAINER_DLL_remove (adh->client->delete_op_head,
871 adh->client->delete_op_tail, adh);
873 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
874 env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
875 acr_msg->id = htonl (adh->r_id);
876 acr_msg->op_result = htonl (success);
877 GNUNET_MQ_send (adh->client->mq, env);
882 ticket_iter (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
883 const char *label, unsigned int rd_count,
884 const struct GNUNET_GNSRECORD_Data *rd)
886 struct AttributeDeleteHandle *adh = cls;
887 struct TicketRecordsEntry *le;
888 int has_changed = GNUNET_NO;
890 for (int i = 0; i < rd_count; i++) {
891 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF != rd[i].record_type)
893 if (0 != memcmp (rd[i].data, &adh->claim->id, sizeof (uint64_t)))
895 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Attribute to delete found (%s)\n",
897 has_changed = GNUNET_YES;
900 if (GNUNET_YES == has_changed) {
901 le = GNUNET_new (struct TicketRecordsEntry);
902 le->data_size = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
903 le->data = GNUNET_malloc (le->data_size);
904 le->rd_count = rd_count;
905 le->label = GNUNET_strdup (label);
906 GNUNET_GNSRECORD_records_serialize (rd_count, rd, le->data_size, le->data);
907 GNUNET_CONTAINER_DLL_insert (adh->tickets_to_update_head,
908 adh->tickets_to_update_tail, le);
910 GNUNET_NAMESTORE_zone_iterator_next (adh->ns_it, 1);
915 update_tickets (void *cls);
919 ticket_updated (void *cls, int32_t success, const char *emsg)
921 struct AttributeDeleteHandle *adh = cls;
923 GNUNET_SCHEDULER_add_now (&update_tickets, adh);
927 update_tickets (void *cls)
929 struct AttributeDeleteHandle *adh = cls;
930 struct TicketRecordsEntry *le;
931 if (NULL == adh->tickets_to_update_head) {
932 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
933 "Finished updatding tickets, success\n");
934 send_delete_response (adh, GNUNET_OK);
938 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Updating %s\n",
939 adh->tickets_to_update_head->label);
940 le = adh->tickets_to_update_head;
941 GNUNET_CONTAINER_DLL_remove (adh->tickets_to_update_head,
942 adh->tickets_to_update_tail, le);
943 struct GNUNET_GNSRECORD_Data rd[le->rd_count];
944 struct GNUNET_GNSRECORD_Data rd_new[le->rd_count - 1];
945 GNUNET_GNSRECORD_records_deserialize (le->data_size, le->data, le->rd_count,
948 for (int i = 0; i < le->rd_count; i++) {
949 if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF == rd[i].record_type) &&
950 (0 == memcmp (rd[i].data, &adh->claim->id, sizeof (uint64_t))))
955 adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh, &adh->identity, le->label,
956 j, rd_new, &ticket_updated, adh);
957 GNUNET_free (le->label);
958 GNUNET_free (le->data);
964 ticket_iter_fin (void *cls)
966 struct AttributeDeleteHandle *adh = cls;
968 GNUNET_SCHEDULER_add_now (&update_tickets, adh);
973 ticket_iter_err (void *cls)
975 struct AttributeDeleteHandle *adh = cls;
977 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Namestore error on delete %s\n",
979 send_delete_response (adh, GNUNET_SYSERR);
985 start_ticket_update (void *cls)
987 struct AttributeDeleteHandle *adh = cls;
988 adh->ns_it = GNUNET_NAMESTORE_zone_iteration_start (
989 nsh, &adh->identity, &ticket_iter_err, adh, &ticket_iter, adh,
990 &ticket_iter_fin, adh);
995 attr_delete_cont (void *cls, int32_t success, const char *emsg)
997 struct AttributeDeleteHandle *adh = cls;
999 if (GNUNET_SYSERR == success) {
1000 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error deleting attribute %s\n",
1002 send_delete_response (adh, GNUNET_SYSERR);
1006 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Updating tickets...\n");
1007 GNUNET_SCHEDULER_add_now (&start_ticket_update, adh);
1012 check_attribute_delete_message (void *cls,
1013 const struct AttributeDeleteMessage *dam)
1017 size = ntohs (dam->header.size);
1018 if (size <= sizeof (struct AttributeDeleteMessage)) {
1020 return GNUNET_SYSERR;
1027 handle_attribute_delete_message (void *cls,
1028 const struct AttributeDeleteMessage *dam)
1030 struct AttributeDeleteHandle *adh;
1031 struct IdpClient *idp = cls;
1033 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Received ATTRIBUTE_DELETE message\n");
1035 data_len = ntohs (dam->attr_len);
1037 adh = GNUNET_new (struct AttributeDeleteHandle);
1038 adh->claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize ((char *)&dam[1], data_len);
1040 adh->r_id = ntohl (dam->id);
1041 adh->identity = dam->identity;
1043 GNUNET_STRINGS_data_to_string_alloc (&adh->claim->id, sizeof (uint64_t));
1044 GNUNET_SERVICE_client_continue (idp->client);
1046 GNUNET_CONTAINER_DLL_insert (idp->delete_op_head, idp->delete_op_tail, adh);
1047 adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh, &adh->identity, adh->label,
1048 0, NULL, &attr_delete_cont, adh);
1052 /*************************************************
1053 * Attrubute iteration
1054 *************************************************/
1057 cleanup_attribute_iter_handle (struct AttributeIterator *ai)
1063 attr_iter_error (void *cls)
1065 struct AttributeIterator *ai = cls;
1066 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to iterate over attributes\n");
1067 GNUNET_CONTAINER_DLL_remove (ai->client->attr_iter_head,
1068 ai->client->attr_iter_tail, ai);
1069 cleanup_attribute_iter_handle (ai);
1070 GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1074 attr_iter_finished (void *cls)
1076 struct AttributeIterator *ai = cls;
1077 struct GNUNET_MQ_Envelope *env;
1078 struct AttributeResultMessage *arm;
1080 env = GNUNET_MQ_msg (arm, GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
1081 arm->id = htonl (ai->request_id);
1082 arm->attr_len = htons (0);
1083 GNUNET_MQ_send (ai->client->mq, env);
1084 GNUNET_CONTAINER_DLL_remove (ai->client->attr_iter_head,
1085 ai->client->attr_iter_tail, ai);
1086 cleanup_attribute_iter_handle (ai);
1090 attr_iter_cb (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1091 const char *label, unsigned int rd_count,
1092 const struct GNUNET_GNSRECORD_Data *rd)
1094 struct AttributeIterator *ai = cls;
1095 struct AttributeResultMessage *arm;
1096 struct GNUNET_MQ_Envelope *env;
1099 if (rd_count != 1) {
1100 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1104 if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR != rd->record_type) {
1105 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1108 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found attribute under: %s\n", label);
1109 env = GNUNET_MQ_msg_extra (arm, rd->data_size,
1110 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
1111 arm->id = htonl (ai->request_id);
1112 arm->attr_len = htons (rd->data_size);
1113 GNUNET_CRYPTO_ecdsa_key_get_public (zone, &arm->identity);
1114 data_tmp = (char *)&arm[1];
1115 GNUNET_memcpy (data_tmp, rd->data, rd->data_size);
1116 GNUNET_MQ_send (ai->client->mq, env);
1120 handle_iteration_start (void *cls,
1121 const struct AttributeIterationStartMessage *ais_msg)
1123 struct IdpClient *idp = cls;
1124 struct AttributeIterator *ai;
1126 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1127 "Received ATTRIBUTE_ITERATION_START message\n");
1128 ai = GNUNET_new (struct AttributeIterator);
1129 ai->request_id = ntohl (ais_msg->id);
1131 ai->identity = ais_msg->identity;
1133 GNUNET_CONTAINER_DLL_insert (idp->attr_iter_head, idp->attr_iter_tail, ai);
1134 ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (
1135 nsh, &ai->identity, &attr_iter_error, ai, &attr_iter_cb, ai,
1136 &attr_iter_finished, ai);
1137 GNUNET_SERVICE_client_continue (idp->client);
1141 handle_iteration_stop (void *cls,
1142 const struct AttributeIterationStopMessage *ais_msg)
1144 struct IdpClient *idp = cls;
1145 struct AttributeIterator *ai;
1148 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n",
1149 "ATTRIBUTE_ITERATION_STOP");
1150 rid = ntohl (ais_msg->id);
1151 for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
1152 if (ai->request_id == rid)
1156 GNUNET_SERVICE_client_drop (idp->client);
1159 GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, idp->attr_iter_tail, ai);
1161 GNUNET_SERVICE_client_continue (idp->client);
1165 handle_iteration_next (void *cls,
1166 const struct AttributeIterationNextMessage *ais_msg)
1168 struct IdpClient *idp = cls;
1169 struct AttributeIterator *ai;
1172 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1173 "Received ATTRIBUTE_ITERATION_NEXT message\n");
1174 rid = ntohl (ais_msg->id);
1175 for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
1176 if (ai->request_id == rid)
1180 GNUNET_SERVICE_client_drop (idp->client);
1183 GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1184 GNUNET_SERVICE_client_continue (idp->client);
1187 /******************************************************
1189 ******************************************************/
1192 ticket_iter_cb (void *cls, struct GNUNET_RECLAIM_Ticket *ticket)
1194 struct TicketIteration *ti = cls;
1195 struct GNUNET_MQ_Envelope *env;
1196 struct TicketResultMessage *trm;
1198 if (NULL == ticket) {
1199 /* send empty response to indicate end of list */
1200 env = GNUNET_MQ_msg (trm, GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
1201 GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head,
1202 ti->client->ticket_iter_tail, ti);
1204 env = GNUNET_MQ_msg_extra (trm, sizeof (struct GNUNET_RECLAIM_Ticket),
1205 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
1206 memcpy (&trm[1], ticket, sizeof (struct GNUNET_RECLAIM_Ticket));
1208 trm->id = htonl (ti->r_id);
1209 GNUNET_MQ_send (ti->client->mq, env);
1215 handle_ticket_iteration_start (
1216 void *cls, const struct TicketIterationStartMessage *tis_msg)
1218 struct IdpClient *client = cls;
1219 struct TicketIteration *ti;
1221 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1222 "Received TICKET_ITERATION_START message\n");
1223 ti = GNUNET_new (struct TicketIteration);
1224 ti->r_id = ntohl (tis_msg->id);
1225 ti->client = client;
1227 GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
1228 client->ticket_iter_tail, ti);
1230 RECLAIM_TICKETS_iteration_start (&tis_msg->identity, &ticket_iter_cb, ti);
1231 GNUNET_SERVICE_client_continue (client->client);
1235 handle_ticket_iteration_stop (void *cls,
1236 const struct TicketIterationStopMessage *tis_msg)
1238 struct IdpClient *client = cls;
1239 struct TicketIteration *ti;
1242 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n",
1243 "TICKET_ITERATION_STOP");
1244 rid = ntohl (tis_msg->id);
1245 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
1246 if (ti->r_id == rid)
1250 GNUNET_SERVICE_client_drop (client->client);
1253 RECLAIM_TICKETS_iteration_stop (ti->iter);
1254 GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
1255 client->ticket_iter_tail, ti);
1257 GNUNET_SERVICE_client_continue (client->client);
1261 handle_ticket_iteration_next (void *cls,
1262 const struct TicketIterationNextMessage *tis_msg)
1264 struct IdpClient *client = cls;
1265 struct TicketIteration *ti;
1268 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1269 "Received TICKET_ITERATION_NEXT message\n");
1270 rid = ntohl (tis_msg->id);
1271 for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
1272 if (ti->r_id == rid)
1276 GNUNET_SERVICE_client_drop (client->client);
1279 RECLAIM_TICKETS_iteration_next (ti->iter);
1280 GNUNET_SERVICE_client_continue (client->client);
1284 * Main function that will be run
1286 * @param cls closure
1287 * @param c the configuration used
1288 * @param server the service handle
1291 run (void *cls, const struct GNUNET_CONFIGURATION_Handle *c,
1292 struct GNUNET_SERVICE_Handle *server)
1296 if (GNUNET_OK != RECLAIM_TICKETS_init (cfg)) {
1297 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1298 "Unable to initialized TICKETS subsystem.\n");
1299 GNUNET_SCHEDULER_shutdown ();
1302 // Connect to identity and namestore services
1303 nsh = GNUNET_NAMESTORE_connect (cfg);
1305 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
1306 "error connecting to namestore");
1309 identity_handle = GNUNET_IDENTITY_connect (cfg, NULL, NULL);
1311 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_time (
1312 cfg, "reclaim", "TOKEN_EXPIRATION_INTERVAL",
1313 &token_expiration_interval)) {
1314 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Time window for zone iteration: %s\n",
1315 GNUNET_STRINGS_relative_time_to_string (
1316 token_expiration_interval, GNUNET_YES));
1318 token_expiration_interval = DEFAULT_TOKEN_EXPIRATION_INTERVAL;
1321 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
1325 * Called whenever a client is disconnected.
1327 * @param cls closure
1328 * @param client identification of the client
1329 * @param app_ctx @a client
1332 client_disconnect_cb (void *cls, struct GNUNET_SERVICE_Client *client,
1335 struct IdpClient *idp = app_ctx;
1336 struct AttributeIterator *ai;
1337 struct TicketIteration *ti;
1338 struct TicketRevocationOperation *rop;
1339 struct TicketIssueOperation *iss;
1340 struct ConsumeTicketOperation *ct;
1341 struct AttributeStoreHandle *as;
1342 struct AttributeDeleteHandle *adh;
1344 // TODO other operations
1346 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client);
1348 while (NULL != (iss = idp->issue_op_head)) {
1349 GNUNET_CONTAINER_DLL_remove (idp->issue_op_head, idp->issue_op_tail, iss);
1352 while (NULL != (ct = idp->consume_op_head)) {
1353 GNUNET_CONTAINER_DLL_remove (idp->consume_op_head, idp->consume_op_tail,
1356 RECLAIM_TICKETS_consume_cancel (ct->ch);
1359 while (NULL != (as = idp->store_op_head)) {
1360 GNUNET_CONTAINER_DLL_remove (idp->store_op_head, idp->store_op_tail, as);
1361 cleanup_as_handle (as);
1363 while (NULL != (adh = idp->delete_op_head)) {
1364 GNUNET_CONTAINER_DLL_remove (idp->delete_op_head, idp->delete_op_tail, adh);
1368 while (NULL != (ai = idp->attr_iter_head)) {
1369 GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, idp->attr_iter_tail, ai);
1370 cleanup_attribute_iter_handle (ai);
1372 while (NULL != (rop = idp->revoke_op_head)) {
1373 GNUNET_CONTAINER_DLL_remove (idp->revoke_op_head, idp->revoke_op_tail, rop);
1374 if (NULL != rop->rh)
1375 RECLAIM_TICKETS_revoke_cancel (rop->rh);
1378 while (NULL != (ti = idp->ticket_iter_head)) {
1379 GNUNET_CONTAINER_DLL_remove (idp->ticket_iter_head, idp->ticket_iter_tail,
1387 * Add a client to our list of active clients.
1390 * @param client client to add
1391 * @param mq message queue for @a client
1392 * @return internal namestore client structure for this client
1395 client_connect_cb (void *cls, struct GNUNET_SERVICE_Client *client,
1396 struct GNUNET_MQ_Handle *mq)
1398 struct IdpClient *idp;
1399 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
1400 idp = GNUNET_new (struct IdpClient);
1401 idp->client = client;
1407 * Define "main" method using service macro.
1409 GNUNET_SERVICE_MAIN (
1410 "reclaim", GNUNET_SERVICE_OPTION_NONE, &run, &client_connect_cb,
1411 &client_disconnect_cb, NULL,
1412 GNUNET_MQ_hd_var_size (attribute_store_message,
1413 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE,
1414 struct AttributeStoreMessage, NULL),
1415 GNUNET_MQ_hd_var_size (attribute_delete_message,
1416 GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_DELETE,
1417 struct AttributeDeleteMessage, NULL),
1418 GNUNET_MQ_hd_fixed_size (
1419 iteration_start, GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_START,
1420 struct AttributeIterationStartMessage, NULL),
1421 GNUNET_MQ_hd_fixed_size (
1422 iteration_next, GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT,
1423 struct AttributeIterationNextMessage, NULL),
1424 GNUNET_MQ_hd_fixed_size (
1425 iteration_stop, GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP,
1426 struct AttributeIterationStopMessage, NULL),
1427 GNUNET_MQ_hd_var_size (issue_ticket_message,
1428 GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET,
1429 struct IssueTicketMessage, NULL),
1430 GNUNET_MQ_hd_var_size (consume_ticket_message,
1431 GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET,
1432 struct ConsumeTicketMessage, NULL),
1433 GNUNET_MQ_hd_fixed_size (ticket_iteration_start,
1434 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_START,
1435 struct TicketIterationStartMessage, NULL),
1436 GNUNET_MQ_hd_fixed_size (ticket_iteration_next,
1437 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_NEXT,
1438 struct TicketIterationNextMessage, NULL),
1439 GNUNET_MQ_hd_fixed_size (ticket_iteration_stop,
1440 GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_STOP,
1441 struct TicketIterationStopMessage, NULL),
1442 GNUNET_MQ_hd_var_size (revoke_ticket_message,
1443 GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET,
1444 struct RevokeTicketMessage, NULL),
1445 GNUNET_MQ_handler_end ());
1446 /* end of gnunet-service-reclaim.c */