update clang-format
[oweals/gnunet.git] / src / reclaim / gnunet-service-reclaim.c
1 /*
2    This file is part of GNUnet.
3    Copyright (C) 2012-2015 GNUnet e.V.
4
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.
9
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.
14
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/>.
17
18    SPDX-License-Identifier: AGPL3.0-or-later
19    */
20 /**
21  * @author Martin Schanzenbach
22  * @file src/reclaim/gnunet-service-reclaim.c
23  * @brief reclaim Service
24  *
25  */
26 #include "platform.h"
27
28 #include "gnunet_util_lib.h"
29
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"
39 #include "reclaim.h"
40
41 /**
42  * First pass state
43  */
44 #define STATE_INIT 0
45
46 /**
47  * Normal operation state
48  */
49 #define STATE_POST_INIT 1
50
51 /**
52  * Minimum interval between updates
53  */
54 #define MIN_WAIT_TIME GNUNET_TIME_UNIT_MINUTES
55
56 /**
57  * Standard token expiration time
58  */
59 #define DEFAULT_TOKEN_EXPIRATION_INTERVAL GNUNET_TIME_UNIT_HOURS
60
61 /**
62  * Identity handle
63  */
64 static struct GNUNET_IDENTITY_Handle *identity_handle;
65
66 /**
67  * Token expiration interval
68  */
69 static struct GNUNET_TIME_Relative token_expiration_interval;
70
71 /**
72  * Namestore handle
73  */
74 static struct GNUNET_NAMESTORE_Handle *nsh;
75
76 /**
77  * Timeout task
78  */
79 static struct GNUNET_SCHEDULER_Task *timeout_task;
80
81 /**
82  * Update task
83  */
84 static struct GNUNET_SCHEDULER_Task *update_task;
85
86 /**
87  * Our configuration.
88  */
89 static const struct GNUNET_CONFIGURATION_Handle *cfg;
90
91 /**
92  * An idp client
93  */
94 struct IdpClient;
95
96 /**
97  * A ticket iteration operation.
98  */
99 struct TicketIteration
100 {
101   /**
102    * DLL
103    */
104   struct TicketIteration *next;
105
106   /**
107    * DLL
108    */
109   struct TicketIteration *prev;
110
111   /**
112    * Client which intiated this zone iteration
113    */
114   struct IdpClient *client;
115
116   /**
117    * The operation id fot the iteration in the response for the client
118    */
119   uint32_t r_id;
120
121   /**
122    * The ticket iterator
123    */
124   struct RECLAIM_TICKETS_Iterator *iter;
125 };
126
127 /**
128  * An attribute iteration operation.
129  */
130 struct AttributeIterator
131 {
132   /**
133    * Next element in the DLL
134    */
135   struct AttributeIterator *next;
136
137   /**
138    * Previous element in the DLL
139    */
140   struct AttributeIterator *prev;
141
142   /**
143    * IDP client which intiated this zone iteration
144    */
145   struct IdpClient *client;
146
147   /**
148    * Key of the zone we are iterating over.
149    */
150   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
151
152   /**
153    * Namestore iterator
154    */
155   struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
156
157   /**
158    * The operation id fot the zone iteration in the response for the client
159    */
160   uint32_t request_id;
161 };
162
163 /**
164  * An idp client
165  */
166 struct IdpClient
167 {
168
169   /**
170    * The client
171    */
172   struct GNUNET_SERVICE_Client *client;
173
174   /**
175    * Message queue for transmission to @e client
176    */
177   struct GNUNET_MQ_Handle *mq;
178
179   /**
180    * Head of the DLL of
181    * Attribute iteration operations in
182    * progress initiated by this client
183    */
184   struct AttributeIterator *attr_iter_head;
185
186   /**
187    * Tail of the DLL of
188    * Attribute iteration operations
189    * in progress initiated by this client
190    */
191   struct AttributeIterator *attr_iter_tail;
192
193   /**
194    * Head of DLL of ticket iteration ops
195    */
196   struct TicketIteration *ticket_iter_head;
197
198   /**
199    * Tail of DLL of ticket iteration ops
200    */
201   struct TicketIteration *ticket_iter_tail;
202
203   /**
204    * Head of DLL of ticket revocation ops
205    */
206   struct TicketRevocationOperation *revoke_op_head;
207
208   /**
209    * Tail of DLL of ticket revocation ops
210    */
211   struct TicketRevocationOperation *revoke_op_tail;
212
213   /**
214    * Head of DLL of ticket issue ops
215    */
216   struct TicketIssueOperation *issue_op_head;
217
218   /**
219    * Tail of DLL of ticket issue ops
220    */
221   struct TicketIssueOperation *issue_op_tail;
222
223   /**
224    * Head of DLL of ticket consume ops
225    */
226   struct ConsumeTicketOperation *consume_op_head;
227
228   /**
229    * Tail of DLL of ticket consume ops
230    */
231   struct ConsumeTicketOperation *consume_op_tail;
232
233   /**
234    * Head of DLL of attribute store ops
235    */
236   struct AttributeStoreHandle *store_op_head;
237
238   /**
239    * Tail of DLL of attribute store ops
240    */
241   struct AttributeStoreHandle *store_op_tail;
242   /**
243    * Head of DLL of attribute delete ops
244    */
245   struct AttributeDeleteHandle *delete_op_head;
246
247   /**
248    * Tail of DLL of attribute delete ops
249    */
250   struct AttributeDeleteHandle *delete_op_tail;
251 };
252
253
254 struct AttributeDeleteHandle
255 {
256   /**
257    * DLL
258    */
259   struct AttributeDeleteHandle *next;
260
261   /**
262    * DLL
263    */
264   struct AttributeDeleteHandle *prev;
265
266   /**
267    * Client connection
268    */
269   struct IdpClient *client;
270
271   /**
272    * Identity
273    */
274   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
275
276
277   /**
278    * QueueEntry
279    */
280   struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
281
282   /**
283    * Iterator
284    */
285   struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
286
287   /**
288    * The attribute to delete
289    */
290   struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
291
292   /**
293    * Tickets to update
294    */
295   struct TicketRecordsEntry *tickets_to_update_head;
296
297   /**
298    * Tickets to update
299    */
300   struct TicketRecordsEntry *tickets_to_update_tail;
301
302   /**
303    * Attribute label
304    */
305   char *label;
306
307   /**
308    * request id
309    */
310   uint32_t r_id;
311 };
312
313
314 struct AttributeStoreHandle
315 {
316   /**
317    * DLL
318    */
319   struct AttributeStoreHandle *next;
320
321   /**
322    * DLL
323    */
324   struct AttributeStoreHandle *prev;
325
326   /**
327    * Client connection
328    */
329   struct IdpClient *client;
330
331   /**
332    * Identity
333    */
334   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
335
336   /**
337    * Identity pubkey
338    */
339   struct GNUNET_CRYPTO_EcdsaPublicKey identity_pkey;
340
341   /**
342    * QueueEntry
343    */
344   struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
345
346   /**
347    * The attribute to store
348    */
349   struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
350
351   /**
352    * The attribute expiration interval
353    */
354   struct GNUNET_TIME_Relative exp;
355
356   /**
357    * request id
358    */
359   uint32_t r_id;
360 };
361
362 struct ConsumeTicketOperation
363 {
364   /**
365    * DLL
366    */
367   struct ConsumeTicketOperation *next;
368
369   /**
370    * DLL
371    */
372   struct ConsumeTicketOperation *prev;
373
374   /**
375    * Client connection
376    */
377   struct IdpClient *client;
378
379   /**
380    * request id
381    */
382   uint32_t r_id;
383
384   /**
385    * Ticket consume handle
386    */
387   struct RECLAIM_TICKETS_ConsumeHandle *ch;
388 };
389
390 /**
391  * Updated attribute IDs
392  */
393 struct TicketAttributeUpdateEntry
394 {
395   /**
396    * DLL
397    */
398   struct TicketAttributeUpdateEntry *next;
399
400   /**
401    * DLL
402    */
403   struct TicketAttributeUpdateEntry *prev;
404
405   /**
406    * The old ID
407    */
408   uint64_t old_id;
409
410   /**
411    * The new ID
412    */
413   uint64_t new_id;
414 };
415
416 /**
417  * Ticket revocation request handle
418  */
419 struct TicketRevocationOperation
420 {
421   /**
422    * DLL
423    */
424   struct TicketRevocationOperation *prev;
425
426   /**
427    * DLL
428    */
429   struct TicketRevocationOperation *next;
430
431   /**
432    * Client connection
433    */
434   struct IdpClient *client;
435
436   /**
437    * Revocation handle
438    */
439   struct RECLAIM_TICKETS_RevokeHandle *rh;
440
441   /**
442    * request id
443    */
444   uint32_t r_id;
445 };
446
447 /**
448  * Ticket issue operation handle
449  */
450 struct TicketIssueOperation
451 {
452   /**
453    * DLL
454    */
455   struct TicketIssueOperation *prev;
456
457   /**
458    * DLL
459    */
460   struct TicketIssueOperation *next;
461
462   /**
463    * Client connection
464    */
465   struct IdpClient *client;
466
467   /**
468    * request id
469    */
470   uint32_t r_id;
471 };
472
473 /**
474  * DLL for ego handles to egos containing the RECLAIM_ATTRS in a
475  * map in json_t format
476  *
477  */
478 struct EgoEntry
479 {
480   /**
481    * DLL
482    */
483   struct EgoEntry *next;
484
485   /**
486    * DLL
487    */
488   struct EgoEntry *prev;
489
490   /**
491    * Ego handle
492    */
493   struct GNUNET_IDENTITY_Ego *ego;
494
495   /**
496    * Attribute map. Contains the attributes as json_t
497    */
498   struct GNUNET_CONTAINER_MultiHashMap *attr_map;
499 };
500
501 /**
502  * Cleanup task
503  */
504 static void
505 cleanup ()
506 {
507   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
508
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);
516   if (NULL != nsh)
517     GNUNET_NAMESTORE_disconnect (nsh);
518 }
519
520 /**
521  * Shutdown task
522  *
523  * @param cls NULL
524  */
525 static void
526 do_shutdown (void *cls)
527 {
528   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down...\n");
529   cleanup ();
530 }
531
532
533 static void
534 send_ticket_result (const struct IdpClient *client,
535                     uint32_t r_id,
536                     const struct GNUNET_RECLAIM_Ticket *ticket,
537                     uint32_t success)
538 {
539   struct TicketResultMessage *irm;
540   struct GNUNET_MQ_Envelope *env;
541   struct GNUNET_RECLAIM_Ticket *ticket_buf;
542
543   if (NULL != ticket) {
544     env = GNUNET_MQ_msg_extra (irm,
545                                sizeof (struct GNUNET_RECLAIM_Ticket),
546                                GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
547     ticket_buf = (struct GNUNET_RECLAIM_Ticket *)&irm[1];
548     *ticket_buf = *ticket;
549   } else {
550     env = GNUNET_MQ_msg (irm, GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
551   }
552   // TODO add success member
553   irm->id = htonl (r_id);
554   GNUNET_MQ_send (client->mq, env);
555 }
556
557 static void
558 issue_ticket_result_cb (void *cls,
559                         struct GNUNET_RECLAIM_Ticket *ticket,
560                         int32_t success,
561                         const char *emsg)
562 {
563   struct TicketIssueOperation *tio = cls;
564   if (GNUNET_OK != success) {
565     send_ticket_result (tio->client, tio->r_id, NULL, GNUNET_SYSERR);
566     GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head,
567                                  tio->client->issue_op_tail,
568                                  tio);
569     GNUNET_free (tio);
570     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error issuing ticket: %s\n", emsg);
571     return;
572   }
573   send_ticket_result (tio->client, tio->r_id, ticket, GNUNET_SYSERR);
574   GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head,
575                                tio->client->issue_op_tail,
576                                tio);
577   GNUNET_free (tio);
578 }
579
580 static int
581 check_issue_ticket_message (void *cls, const struct IssueTicketMessage *im)
582 {
583   uint16_t size;
584
585   size = ntohs (im->header.size);
586   if (size <= sizeof (struct IssueTicketMessage)) {
587     GNUNET_break (0);
588     return GNUNET_SYSERR;
589   }
590   return GNUNET_OK;
591 }
592
593 static void
594 handle_issue_ticket_message (void *cls, const struct IssueTicketMessage *im)
595 {
596   struct TicketIssueOperation *tio;
597   struct IdpClient *idp = cls;
598   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
599   size_t attrs_len;
600
601   tio = GNUNET_new (struct TicketIssueOperation);
602   attrs_len = ntohs (im->attr_len);
603   attrs = GNUNET_RECLAIM_ATTRIBUTE_list_deserialize ((char *)&im[1], attrs_len);
604   tio->r_id = ntohl (im->id);
605   tio->client = idp;
606   GNUNET_CONTAINER_DLL_insert (idp->issue_op_head, idp->issue_op_tail, tio);
607   RECLAIM_TICKETS_issue (&im->identity,
608                          attrs,
609                          &im->rp,
610                          &issue_ticket_result_cb,
611                          tio);
612   GNUNET_SERVICE_client_continue (idp->client);
613   GNUNET_RECLAIM_ATTRIBUTE_list_destroy (attrs);
614 }
615
616 /**********************************************************
617  * Revocation
618  **********************************************************/
619
620 static void
621 revoke_result_cb (void *cls, int32_t success)
622 {
623   struct TicketRevocationOperation *rop = cls;
624   struct GNUNET_MQ_Envelope *env;
625   struct RevokeTicketResultMessage *trm;
626
627   rop->rh = NULL;
628   env = GNUNET_MQ_msg (trm, GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT);
629   trm->id = htonl (rop->r_id);
630   trm->success = htonl (success);
631   GNUNET_MQ_send (rop->client->mq, env);
632   GNUNET_CONTAINER_DLL_remove (rop->client->revoke_op_head,
633                                rop->client->revoke_op_tail,
634                                rop);
635   GNUNET_free (rop);
636 }
637
638
639 static int
640 check_revoke_ticket_message (void *cls, const struct RevokeTicketMessage *im)
641 {
642   uint16_t size;
643
644   size = ntohs (im->header.size);
645   if (size <= sizeof (struct RevokeTicketMessage)) {
646     GNUNET_break (0);
647     return GNUNET_SYSERR;
648   }
649   return GNUNET_OK;
650 }
651
652 static void
653 handle_revoke_ticket_message (void *cls, const struct RevokeTicketMessage *rm)
654 {
655   struct TicketRevocationOperation *rop;
656   struct IdpClient *idp = cls;
657   struct GNUNET_RECLAIM_Ticket *ticket;
658
659   rop = GNUNET_new (struct TicketRevocationOperation);
660   ticket = (struct GNUNET_RECLAIM_Ticket *)&rm[1];
661   rop->r_id = ntohl (rm->id);
662   rop->client = idp;
663   GNUNET_CONTAINER_DLL_insert (idp->revoke_op_head, idp->revoke_op_tail, rop);
664   rop->rh
665     = RECLAIM_TICKETS_revoke (ticket, &rm->identity, &revoke_result_cb, rop);
666   GNUNET_SERVICE_client_continue (idp->client);
667 }
668
669 static int
670 check_consume_ticket_message (void *cls, const struct ConsumeTicketMessage *cm)
671 {
672   uint16_t size;
673
674   size = ntohs (cm->header.size);
675   if (size <= sizeof (struct ConsumeTicketMessage)) {
676     GNUNET_break (0);
677     return GNUNET_SYSERR;
678   }
679   return GNUNET_OK;
680 }
681
682 static void
683 consume_result_cb (void *cls,
684                    const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
685                    const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
686                    int32_t success,
687                    const char *emsg)
688 {
689   struct ConsumeTicketOperation *cop = cls;
690   struct ConsumeTicketResultMessage *crm;
691   struct GNUNET_MQ_Envelope *env;
692   char *data_tmp;
693   size_t attrs_len;
694   if (GNUNET_OK != success) {
695     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error consuming ticket: %s\n", emsg);
696   }
697   attrs_len = GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (attrs);
698   env = GNUNET_MQ_msg_extra (crm,
699                              attrs_len,
700                              GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT);
701   crm->id = htonl (cop->r_id);
702   crm->attrs_len = htons (attrs_len);
703   crm->identity = *identity;
704   crm->result = htonl (success);
705   data_tmp = (char *)&crm[1];
706   GNUNET_RECLAIM_ATTRIBUTE_list_serialize (attrs, data_tmp);
707   GNUNET_MQ_send (cop->client->mq, env);
708   GNUNET_CONTAINER_DLL_remove (cop->client->consume_op_head,
709                                cop->client->consume_op_tail,
710                                cop);
711   GNUNET_free (cop);
712 }
713
714 static void
715 handle_consume_ticket_message (void *cls, const struct ConsumeTicketMessage *cm)
716 {
717   struct ConsumeTicketOperation *cop;
718   struct GNUNET_RECLAIM_Ticket *ticket;
719   struct IdpClient *idp = cls;
720
721   cop = GNUNET_new (struct ConsumeTicketOperation);
722   cop->r_id = ntohl (cm->id);
723   cop->client = idp;
724   ticket = (struct GNUNET_RECLAIM_Ticket *)&cm[1];
725   cop->ch
726     = RECLAIM_TICKETS_consume (&cm->identity, ticket, &consume_result_cb, cop);
727   GNUNET_CONTAINER_DLL_insert (idp->consume_op_head, idp->consume_op_tail, cop);
728   GNUNET_SERVICE_client_continue (idp->client);
729 }
730
731 /*****************************************
732  * Attribute store
733  *****************************************/
734
735 /**
736  * Cleanup attribute store handle
737  *
738  * @param handle handle to clean up
739  */
740 static void
741 cleanup_as_handle (struct AttributeStoreHandle *ash)
742 {
743   if (NULL != ash->ns_qe)
744     GNUNET_NAMESTORE_cancel (ash->ns_qe);
745   if (NULL != ash->claim)
746     GNUNET_free (ash->claim);
747   GNUNET_free (ash);
748 }
749
750 static void
751 attr_store_cont (void *cls, int32_t success, const char *emsg)
752 {
753   struct AttributeStoreHandle *ash = cls;
754   struct GNUNET_MQ_Envelope *env;
755   struct SuccessResultMessage *acr_msg;
756
757   ash->ns_qe = NULL;
758   GNUNET_CONTAINER_DLL_remove (ash->client->store_op_head,
759                                ash->client->store_op_tail,
760                                ash);
761
762   if (GNUNET_SYSERR == success) {
763     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
764                 "Failed to store attribute %s\n",
765                 emsg);
766     cleanup_as_handle (ash);
767     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
768     return;
769   }
770
771   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
772   env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
773   acr_msg->id = htonl (ash->r_id);
774   acr_msg->op_result = htonl (GNUNET_OK);
775   GNUNET_MQ_send (ash->client->mq, env);
776   cleanup_as_handle (ash);
777 }
778
779 /**
780  * Adds a new attribute
781  *
782  * @param cls the AttributeStoreHandle
783  */
784 static void
785 attr_store_task (void *cls)
786 {
787   struct AttributeStoreHandle *ash = cls;
788   struct GNUNET_GNSRECORD_Data rd[1];
789   char *buf;
790   char *label;
791   size_t buf_size;
792
793   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Storing attribute\n");
794   buf_size = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (ash->claim);
795   buf = GNUNET_malloc (buf_size);
796   // Give the ash a new id if unset
797   if (0 == ash->claim->id)
798     ash->claim->id
799       = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX);
800   GNUNET_RECLAIM_ATTRIBUTE_serialize (ash->claim, buf);
801   label
802     = GNUNET_STRINGS_data_to_string_alloc (&ash->claim->id, sizeof (uint64_t));
803   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting with label %s\n", label);
804
805   rd[0].data_size = buf_size;
806   rd[0].data = buf;
807   rd[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR;
808   rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
809   rd[0].expiration_time = ash->exp.rel_value_us;
810   ash->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
811                                                &ash->identity,
812                                                label,
813                                                1,
814                                                rd,
815                                                &attr_store_cont,
816                                                ash);
817   GNUNET_free (buf);
818 }
819
820 static int
821 check_attribute_store_message (void *cls,
822                                const struct AttributeStoreMessage *sam)
823 {
824   uint16_t size;
825
826   size = ntohs (sam->header.size);
827   if (size <= sizeof (struct AttributeStoreMessage)) {
828     GNUNET_break (0);
829     return GNUNET_SYSERR;
830   }
831   return GNUNET_OK;
832 }
833
834 static void
835 handle_attribute_store_message (void *cls,
836                                 const struct AttributeStoreMessage *sam)
837 {
838   struct AttributeStoreHandle *ash;
839   struct IdpClient *idp = cls;
840   size_t data_len;
841   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTRIBUTE_STORE message\n");
842
843   data_len = ntohs (sam->attr_len);
844
845   ash = GNUNET_new (struct AttributeStoreHandle);
846   ash->claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize ((char *)&sam[1], data_len);
847
848   ash->r_id = ntohl (sam->id);
849   ash->identity = sam->identity;
850   ash->exp.rel_value_us = GNUNET_ntohll (sam->exp);
851   GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity, &ash->identity_pkey);
852
853   GNUNET_SERVICE_client_continue (idp->client);
854   ash->client = idp;
855   GNUNET_CONTAINER_DLL_insert (idp->store_op_head, idp->store_op_tail, ash);
856   GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
857 }
858
859
860 static void
861 cleanup_adh (struct AttributeDeleteHandle *adh)
862 {
863   struct TicketRecordsEntry *le;
864   if (NULL != adh->ns_it)
865     GNUNET_NAMESTORE_zone_iteration_stop (adh->ns_it);
866   if (NULL != adh->ns_qe)
867     GNUNET_NAMESTORE_cancel (adh->ns_qe);
868   if (NULL != adh->label)
869     GNUNET_free (adh->label);
870   if (NULL != adh->claim)
871     GNUNET_free (adh->claim);
872   while (NULL != (le = adh->tickets_to_update_head)) {
873     GNUNET_CONTAINER_DLL_remove (adh->tickets_to_update_head,
874                                  adh->tickets_to_update_tail,
875                                  le);
876     if (NULL != le->label)
877       GNUNET_free (le->label);
878     if (NULL != le->data)
879       GNUNET_free (le->data);
880     GNUNET_free (le);
881   }
882   GNUNET_free (adh);
883 }
884
885
886 static void
887 send_delete_response (struct AttributeDeleteHandle *adh, int32_t success)
888 {
889   struct GNUNET_MQ_Envelope *env;
890   struct SuccessResultMessage *acr_msg;
891
892   GNUNET_CONTAINER_DLL_remove (adh->client->delete_op_head,
893                                adh->client->delete_op_tail,
894                                adh);
895
896   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
897   env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
898   acr_msg->id = htonl (adh->r_id);
899   acr_msg->op_result = htonl (success);
900   GNUNET_MQ_send (adh->client->mq, env);
901 }
902
903
904 static void
905 ticket_iter (void *cls,
906              const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
907              const char *label,
908              unsigned int rd_count,
909              const struct GNUNET_GNSRECORD_Data *rd)
910 {
911   struct AttributeDeleteHandle *adh = cls;
912   struct TicketRecordsEntry *le;
913   int has_changed = GNUNET_NO;
914
915   for (int i = 0; i < rd_count; i++) {
916     if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF != rd[i].record_type)
917       continue;
918     if (0 != memcmp (rd[i].data, &adh->claim->id, sizeof (uint64_t)))
919       continue;
920     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
921                 "Attribute to delete found (%s)\n",
922                 adh->label);
923     has_changed = GNUNET_YES;
924     break;
925   }
926   if (GNUNET_YES == has_changed) {
927     le = GNUNET_new (struct TicketRecordsEntry);
928     le->data_size = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
929     le->data = GNUNET_malloc (le->data_size);
930     le->rd_count = rd_count;
931     le->label = GNUNET_strdup (label);
932     GNUNET_GNSRECORD_records_serialize (rd_count, rd, le->data_size, le->data);
933     GNUNET_CONTAINER_DLL_insert (adh->tickets_to_update_head,
934                                  adh->tickets_to_update_tail,
935                                  le);
936   }
937   GNUNET_NAMESTORE_zone_iterator_next (adh->ns_it, 1);
938 }
939
940
941 static void
942 update_tickets (void *cls);
943
944
945 static void
946 ticket_updated (void *cls, int32_t success, const char *emsg)
947 {
948   struct AttributeDeleteHandle *adh = cls;
949   adh->ns_qe = NULL;
950   GNUNET_SCHEDULER_add_now (&update_tickets, adh);
951 }
952
953 static void
954 update_tickets (void *cls)
955 {
956   struct AttributeDeleteHandle *adh = cls;
957   struct TicketRecordsEntry *le;
958   if (NULL == adh->tickets_to_update_head) {
959     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
960                 "Finished updatding tickets, success\n");
961     send_delete_response (adh, GNUNET_OK);
962     cleanup_adh (adh);
963     return;
964   }
965   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
966               "Updating %s\n",
967               adh->tickets_to_update_head->label);
968   le = adh->tickets_to_update_head;
969   GNUNET_CONTAINER_DLL_remove (adh->tickets_to_update_head,
970                                adh->tickets_to_update_tail,
971                                le);
972   struct GNUNET_GNSRECORD_Data rd[le->rd_count];
973   struct GNUNET_GNSRECORD_Data rd_new[le->rd_count - 1];
974   GNUNET_GNSRECORD_records_deserialize (le->data_size,
975                                         le->data,
976                                         le->rd_count,
977                                         rd);
978   int j = 0;
979   for (int i = 0; i < le->rd_count; i++) {
980     if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF == rd[i].record_type)
981         && (0 == memcmp (rd[i].data, &adh->claim->id, sizeof (uint64_t))))
982       continue;
983     rd_new[j] = rd[i];
984     j++;
985   }
986   adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
987                                                &adh->identity,
988                                                le->label,
989                                                j,
990                                                rd_new,
991                                                &ticket_updated,
992                                                adh);
993   GNUNET_free (le->label);
994   GNUNET_free (le->data);
995   GNUNET_free (le);
996 }
997
998
999 static void
1000 ticket_iter_fin (void *cls)
1001 {
1002   struct AttributeDeleteHandle *adh = cls;
1003   adh->ns_it = NULL;
1004   GNUNET_SCHEDULER_add_now (&update_tickets, adh);
1005 }
1006
1007
1008 static void
1009 ticket_iter_err (void *cls)
1010 {
1011   struct AttributeDeleteHandle *adh = cls;
1012   adh->ns_it = NULL;
1013   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1014               "Namestore error on delete %s\n",
1015               adh->label);
1016   send_delete_response (adh, GNUNET_SYSERR);
1017   cleanup_adh (adh);
1018 }
1019
1020
1021 static void
1022 start_ticket_update (void *cls)
1023 {
1024   struct AttributeDeleteHandle *adh = cls;
1025   adh->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh,
1026                                                       &adh->identity,
1027                                                       &ticket_iter_err,
1028                                                       adh,
1029                                                       &ticket_iter,
1030                                                       adh,
1031                                                       &ticket_iter_fin,
1032                                                       adh);
1033 }
1034
1035
1036 static void
1037 attr_delete_cont (void *cls, int32_t success, const char *emsg)
1038 {
1039   struct AttributeDeleteHandle *adh = cls;
1040   adh->ns_qe = NULL;
1041   if (GNUNET_SYSERR == success) {
1042     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1043                 "Error deleting attribute %s\n",
1044                 adh->label);
1045     send_delete_response (adh, GNUNET_SYSERR);
1046     cleanup_adh (adh);
1047     return;
1048   }
1049   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Updating tickets...\n");
1050   GNUNET_SCHEDULER_add_now (&start_ticket_update, adh);
1051 }
1052
1053
1054 static int
1055 check_attribute_delete_message (void *cls,
1056                                 const struct AttributeDeleteMessage *dam)
1057 {
1058   uint16_t size;
1059
1060   size = ntohs (dam->header.size);
1061   if (size <= sizeof (struct AttributeDeleteMessage)) {
1062     GNUNET_break (0);
1063     return GNUNET_SYSERR;
1064   }
1065   return GNUNET_OK;
1066 }
1067
1068
1069 static void
1070 handle_attribute_delete_message (void *cls,
1071                                  const struct AttributeDeleteMessage *dam)
1072 {
1073   struct AttributeDeleteHandle *adh;
1074   struct IdpClient *idp = cls;
1075   size_t data_len;
1076   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Received ATTRIBUTE_DELETE message\n");
1077
1078   data_len = ntohs (dam->attr_len);
1079
1080   adh = GNUNET_new (struct AttributeDeleteHandle);
1081   adh->claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize ((char *)&dam[1], data_len);
1082
1083   adh->r_id = ntohl (dam->id);
1084   adh->identity = dam->identity;
1085   adh->label
1086     = GNUNET_STRINGS_data_to_string_alloc (&adh->claim->id, sizeof (uint64_t));
1087   GNUNET_SERVICE_client_continue (idp->client);
1088   adh->client = idp;
1089   GNUNET_CONTAINER_DLL_insert (idp->delete_op_head, idp->delete_op_tail, adh);
1090   adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1091                                                &adh->identity,
1092                                                adh->label,
1093                                                0,
1094                                                NULL,
1095                                                &attr_delete_cont,
1096                                                adh);
1097 }
1098
1099
1100 /*************************************************
1101  * Attrubute iteration
1102  *************************************************/
1103
1104 static void
1105 cleanup_attribute_iter_handle (struct AttributeIterator *ai)
1106 {
1107   GNUNET_free (ai);
1108 }
1109
1110 static void
1111 attr_iter_error (void *cls)
1112 {
1113   struct AttributeIterator *ai = cls;
1114   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to iterate over attributes\n");
1115   GNUNET_CONTAINER_DLL_remove (ai->client->attr_iter_head,
1116                                ai->client->attr_iter_tail,
1117                                ai);
1118   cleanup_attribute_iter_handle (ai);
1119   GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1120 }
1121
1122 static void
1123 attr_iter_finished (void *cls)
1124 {
1125   struct AttributeIterator *ai = cls;
1126   struct GNUNET_MQ_Envelope *env;
1127   struct AttributeResultMessage *arm;
1128
1129   env = GNUNET_MQ_msg (arm, GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
1130   arm->id = htonl (ai->request_id);
1131   arm->attr_len = htons (0);
1132   GNUNET_MQ_send (ai->client->mq, env);
1133   GNUNET_CONTAINER_DLL_remove (ai->client->attr_iter_head,
1134                                ai->client->attr_iter_tail,
1135                                ai);
1136   cleanup_attribute_iter_handle (ai);
1137 }
1138
1139 static void
1140 attr_iter_cb (void *cls,
1141               const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1142               const char *label,
1143               unsigned int rd_count,
1144               const struct GNUNET_GNSRECORD_Data *rd)
1145 {
1146   struct AttributeIterator *ai = cls;
1147   struct AttributeResultMessage *arm;
1148   struct GNUNET_MQ_Envelope *env;
1149   char *data_tmp;
1150
1151   if (rd_count != 1) {
1152     GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1153     return;
1154   }
1155
1156   if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR != rd->record_type) {
1157     GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1158     return;
1159   }
1160   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found attribute under: %s\n", label);
1161   env = GNUNET_MQ_msg_extra (arm,
1162                              rd->data_size,
1163                              GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
1164   arm->id = htonl (ai->request_id);
1165   arm->attr_len = htons (rd->data_size);
1166   GNUNET_CRYPTO_ecdsa_key_get_public (zone, &arm->identity);
1167   data_tmp = (char *)&arm[1];
1168   GNUNET_memcpy (data_tmp, rd->data, rd->data_size);
1169   GNUNET_MQ_send (ai->client->mq, env);
1170 }
1171
1172 static void
1173 handle_iteration_start (void *cls,
1174                         const struct AttributeIterationStartMessage *ais_msg)
1175 {
1176   struct IdpClient *idp = cls;
1177   struct AttributeIterator *ai;
1178
1179   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1180               "Received ATTRIBUTE_ITERATION_START message\n");
1181   ai = GNUNET_new (struct AttributeIterator);
1182   ai->request_id = ntohl (ais_msg->id);
1183   ai->client = idp;
1184   ai->identity = ais_msg->identity;
1185
1186   GNUNET_CONTAINER_DLL_insert (idp->attr_iter_head, idp->attr_iter_tail, ai);
1187   ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh,
1188                                                      &ai->identity,
1189                                                      &attr_iter_error,
1190                                                      ai,
1191                                                      &attr_iter_cb,
1192                                                      ai,
1193                                                      &attr_iter_finished,
1194                                                      ai);
1195   GNUNET_SERVICE_client_continue (idp->client);
1196 }
1197
1198 static void
1199 handle_iteration_stop (void *cls,
1200                        const struct AttributeIterationStopMessage *ais_msg)
1201 {
1202   struct IdpClient *idp = cls;
1203   struct AttributeIterator *ai;
1204   uint32_t rid;
1205
1206   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1207               "Received `%s' message\n",
1208               "ATTRIBUTE_ITERATION_STOP");
1209   rid = ntohl (ais_msg->id);
1210   for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
1211     if (ai->request_id == rid)
1212       break;
1213   if (NULL == ai) {
1214     GNUNET_break (0);
1215     GNUNET_SERVICE_client_drop (idp->client);
1216     return;
1217   }
1218   GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, idp->attr_iter_tail, ai);
1219   GNUNET_free (ai);
1220   GNUNET_SERVICE_client_continue (idp->client);
1221 }
1222
1223 static void
1224 handle_iteration_next (void *cls,
1225                        const struct AttributeIterationNextMessage *ais_msg)
1226 {
1227   struct IdpClient *idp = cls;
1228   struct AttributeIterator *ai;
1229   uint32_t rid;
1230
1231   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1232               "Received ATTRIBUTE_ITERATION_NEXT message\n");
1233   rid = ntohl (ais_msg->id);
1234   for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
1235     if (ai->request_id == rid)
1236       break;
1237   if (NULL == ai) {
1238     GNUNET_break (0);
1239     GNUNET_SERVICE_client_drop (idp->client);
1240     return;
1241   }
1242   GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1243   GNUNET_SERVICE_client_continue (idp->client);
1244 }
1245
1246 /******************************************************
1247  * Ticket iteration
1248  ******************************************************/
1249
1250 static void
1251 ticket_iter_cb (void *cls, struct GNUNET_RECLAIM_Ticket *ticket)
1252 {
1253   struct TicketIteration *ti = cls;
1254   struct GNUNET_MQ_Envelope *env;
1255   struct TicketResultMessage *trm;
1256
1257   if (NULL == ticket) {
1258     /* send empty response to indicate end of list */
1259     env = GNUNET_MQ_msg (trm, GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
1260     GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head,
1261                                  ti->client->ticket_iter_tail,
1262                                  ti);
1263   } else {
1264     env = GNUNET_MQ_msg_extra (trm,
1265                                sizeof (struct GNUNET_RECLAIM_Ticket),
1266                                GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
1267     memcpy (&trm[1], ticket, sizeof (struct GNUNET_RECLAIM_Ticket));
1268   }
1269   trm->id = htonl (ti->r_id);
1270   GNUNET_MQ_send (ti->client->mq, env);
1271   if (NULL == ticket)
1272     GNUNET_free (ti);
1273 }
1274
1275 static void
1276 handle_ticket_iteration_start (
1277   void *cls,
1278   const struct TicketIterationStartMessage *tis_msg)
1279 {
1280   struct IdpClient *client = cls;
1281   struct TicketIteration *ti;
1282
1283   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1284               "Received TICKET_ITERATION_START message\n");
1285   ti = GNUNET_new (struct TicketIteration);
1286   ti->r_id = ntohl (tis_msg->id);
1287   ti->client = client;
1288
1289   GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
1290                                client->ticket_iter_tail,
1291                                ti);
1292   ti->iter
1293     = RECLAIM_TICKETS_iteration_start (&tis_msg->identity, &ticket_iter_cb, ti);
1294   GNUNET_SERVICE_client_continue (client->client);
1295 }
1296
1297 static void
1298 handle_ticket_iteration_stop (void *cls,
1299                               const struct TicketIterationStopMessage *tis_msg)
1300 {
1301   struct IdpClient *client = cls;
1302   struct TicketIteration *ti;
1303   uint32_t rid;
1304
1305   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1306               "Received `%s' message\n",
1307               "TICKET_ITERATION_STOP");
1308   rid = ntohl (tis_msg->id);
1309   for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
1310     if (ti->r_id == rid)
1311       break;
1312   if (NULL == ti) {
1313     GNUNET_break (0);
1314     GNUNET_SERVICE_client_drop (client->client);
1315     return;
1316   }
1317   RECLAIM_TICKETS_iteration_stop (ti->iter);
1318   GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
1319                                client->ticket_iter_tail,
1320                                ti);
1321   GNUNET_free (ti);
1322   GNUNET_SERVICE_client_continue (client->client);
1323 }
1324
1325 static void
1326 handle_ticket_iteration_next (void *cls,
1327                               const struct TicketIterationNextMessage *tis_msg)
1328 {
1329   struct IdpClient *client = cls;
1330   struct TicketIteration *ti;
1331   uint32_t rid;
1332
1333   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1334               "Received TICKET_ITERATION_NEXT message\n");
1335   rid = ntohl (tis_msg->id);
1336   for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
1337     if (ti->r_id == rid)
1338       break;
1339   if (NULL == ti) {
1340     GNUNET_break (0);
1341     GNUNET_SERVICE_client_drop (client->client);
1342     return;
1343   }
1344   RECLAIM_TICKETS_iteration_next (ti->iter);
1345   GNUNET_SERVICE_client_continue (client->client);
1346 }
1347
1348 /**
1349  * Main function that will be run
1350  *
1351  * @param cls closure
1352  * @param c the configuration used
1353  * @param server the service handle
1354  */
1355 static void
1356 run (void *cls,
1357      const struct GNUNET_CONFIGURATION_Handle *c,
1358      struct GNUNET_SERVICE_Handle *server)
1359 {
1360   cfg = c;
1361
1362   if (GNUNET_OK != RECLAIM_TICKETS_init (cfg)) {
1363     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1364                 "Unable to initialized TICKETS subsystem.\n");
1365     GNUNET_SCHEDULER_shutdown ();
1366     return;
1367   }
1368   // Connect to identity and namestore services
1369   nsh = GNUNET_NAMESTORE_connect (cfg);
1370   if (NULL == nsh) {
1371     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
1372                          "error connecting to namestore");
1373   }
1374
1375   identity_handle = GNUNET_IDENTITY_connect (cfg, NULL, NULL);
1376
1377   if (GNUNET_OK
1378       == GNUNET_CONFIGURATION_get_value_time (cfg,
1379                                               "reclaim",
1380                                               "TOKEN_EXPIRATION_INTERVAL",
1381                                               &token_expiration_interval)) {
1382     GNUNET_log (
1383       GNUNET_ERROR_TYPE_DEBUG,
1384       "Time window for zone iteration: %s\n",
1385       GNUNET_STRINGS_relative_time_to_string (token_expiration_interval,
1386                                               GNUNET_YES));
1387   } else {
1388     token_expiration_interval = DEFAULT_TOKEN_EXPIRATION_INTERVAL;
1389   }
1390
1391   GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
1392 }
1393
1394 /**
1395  * Called whenever a client is disconnected.
1396  *
1397  * @param cls closure
1398  * @param client identification of the client
1399  * @param app_ctx @a client
1400  */
1401 static void
1402 client_disconnect_cb (void *cls,
1403                       struct GNUNET_SERVICE_Client *client,
1404                       void *app_ctx)
1405 {
1406   struct IdpClient *idp = app_ctx;
1407   struct AttributeIterator *ai;
1408   struct TicketIteration *ti;
1409   struct TicketRevocationOperation *rop;
1410   struct TicketIssueOperation *iss;
1411   struct ConsumeTicketOperation *ct;
1412   struct AttributeStoreHandle *as;
1413   struct AttributeDeleteHandle *adh;
1414
1415   // TODO other operations
1416
1417   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client);
1418
1419   while (NULL != (iss = idp->issue_op_head)) {
1420     GNUNET_CONTAINER_DLL_remove (idp->issue_op_head, idp->issue_op_tail, iss);
1421     GNUNET_free (iss);
1422   }
1423   while (NULL != (ct = idp->consume_op_head)) {
1424     GNUNET_CONTAINER_DLL_remove (idp->consume_op_head,
1425                                  idp->consume_op_tail,
1426                                  ct);
1427     if (NULL != ct->ch)
1428       RECLAIM_TICKETS_consume_cancel (ct->ch);
1429     GNUNET_free (ct);
1430   }
1431   while (NULL != (as = idp->store_op_head)) {
1432     GNUNET_CONTAINER_DLL_remove (idp->store_op_head, idp->store_op_tail, as);
1433     cleanup_as_handle (as);
1434   }
1435   while (NULL != (adh = idp->delete_op_head)) {
1436     GNUNET_CONTAINER_DLL_remove (idp->delete_op_head, idp->delete_op_tail, adh);
1437     cleanup_adh (adh);
1438   }
1439
1440   while (NULL != (ai = idp->attr_iter_head)) {
1441     GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, idp->attr_iter_tail, ai);
1442     cleanup_attribute_iter_handle (ai);
1443   }
1444   while (NULL != (rop = idp->revoke_op_head)) {
1445     GNUNET_CONTAINER_DLL_remove (idp->revoke_op_head, idp->revoke_op_tail, rop);
1446     if (NULL != rop->rh)
1447       RECLAIM_TICKETS_revoke_cancel (rop->rh);
1448     GNUNET_free (rop);
1449   }
1450   while (NULL != (ti = idp->ticket_iter_head)) {
1451     GNUNET_CONTAINER_DLL_remove (idp->ticket_iter_head,
1452                                  idp->ticket_iter_tail,
1453                                  ti);
1454     GNUNET_free (ti);
1455   }
1456   GNUNET_free (idp);
1457 }
1458
1459 /**
1460  * Add a client to our list of active clients.
1461  *
1462  * @param cls NULL
1463  * @param client client to add
1464  * @param mq message queue for @a client
1465  * @return internal namestore client structure for this client
1466  */
1467 static void *
1468 client_connect_cb (void *cls,
1469                    struct GNUNET_SERVICE_Client *client,
1470                    struct GNUNET_MQ_Handle *mq)
1471 {
1472   struct IdpClient *idp;
1473   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
1474   idp = GNUNET_new (struct IdpClient);
1475   idp->client = client;
1476   idp->mq = mq;
1477   return idp;
1478 }
1479
1480 /**
1481  * Define "main" method using service macro.
1482  */
1483 GNUNET_SERVICE_MAIN (
1484   "reclaim",
1485   GNUNET_SERVICE_OPTION_NONE,
1486   &run,
1487   &client_connect_cb,
1488   &client_disconnect_cb,
1489   NULL,
1490   GNUNET_MQ_hd_var_size (attribute_store_message,
1491                          GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE,
1492                          struct AttributeStoreMessage,
1493                          NULL),
1494   GNUNET_MQ_hd_var_size (attribute_delete_message,
1495                          GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_DELETE,
1496                          struct AttributeDeleteMessage,
1497                          NULL),
1498   GNUNET_MQ_hd_fixed_size (
1499     iteration_start,
1500     GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_START,
1501     struct AttributeIterationStartMessage,
1502     NULL),
1503   GNUNET_MQ_hd_fixed_size (iteration_next,
1504                            GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT,
1505                            struct AttributeIterationNextMessage,
1506                            NULL),
1507   GNUNET_MQ_hd_fixed_size (iteration_stop,
1508                            GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP,
1509                            struct AttributeIterationStopMessage,
1510                            NULL),
1511   GNUNET_MQ_hd_var_size (issue_ticket_message,
1512                          GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET,
1513                          struct IssueTicketMessage,
1514                          NULL),
1515   GNUNET_MQ_hd_var_size (consume_ticket_message,
1516                          GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET,
1517                          struct ConsumeTicketMessage,
1518                          NULL),
1519   GNUNET_MQ_hd_fixed_size (ticket_iteration_start,
1520                            GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_START,
1521                            struct TicketIterationStartMessage,
1522                            NULL),
1523   GNUNET_MQ_hd_fixed_size (ticket_iteration_next,
1524                            GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_NEXT,
1525                            struct TicketIterationNextMessage,
1526                            NULL),
1527   GNUNET_MQ_hd_fixed_size (ticket_iteration_stop,
1528                            GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_STOP,
1529                            struct TicketIterationStopMessage,
1530                            NULL),
1531   GNUNET_MQ_hd_var_size (revoke_ticket_message,
1532                          GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET,
1533                          struct RevokeTicketMessage,
1534                          NULL),
1535   GNUNET_MQ_handler_end ());
1536 /* end of gnunet-service-reclaim.c */