clang-format and cleanup
[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 #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"
35 #include "reclaim.h"
36
37
38 /**
39  * Namestore handle
40  */
41 static struct GNUNET_NAMESTORE_Handle *nsh;
42
43 /**
44  * Timeout task
45  */
46 static struct GNUNET_SCHEDULER_Task *timeout_task;
47
48 /**
49  * Our configuration.
50  */
51 static const struct GNUNET_CONFIGURATION_Handle *cfg;
52
53 /**
54  * An idp client
55  */
56 struct IdpClient;
57
58 /**
59  * A ticket iteration operation.
60  */
61 struct TicketIteration
62 {
63   /**
64    * DLL
65    */
66   struct TicketIteration *next;
67
68   /**
69    * DLL
70    */
71   struct TicketIteration *prev;
72
73   /**
74    * Client which intiated this zone iteration
75    */
76   struct IdpClient *client;
77
78   /**
79    * The operation id fot the iteration in the response for the client
80    */
81   uint32_t r_id;
82
83   /**
84    * The ticket iterator
85    */
86   struct RECLAIM_TICKETS_Iterator *iter;
87 };
88
89
90 /**
91  * An attribute iteration operation.
92  */
93 struct AttributeIterator
94 {
95   /**
96    * Next element in the DLL
97    */
98   struct AttributeIterator *next;
99
100   /**
101    * Previous element in the DLL
102    */
103   struct AttributeIterator *prev;
104
105   /**
106    * IDP client which intiated this zone iteration
107    */
108   struct IdpClient *client;
109
110   /**
111    * Key of the zone we are iterating over.
112    */
113   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
114
115   /**
116    * Namestore iterator
117    */
118   struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
119
120   /**
121    * The operation id fot the zone iteration in the response for the client
122    */
123   uint32_t request_id;
124 };
125
126
127 /**
128  * An idp client
129  */
130 struct IdpClient
131 {
132   /**
133    * DLL
134    */
135   struct IdpClient *prev;
136
137   /**
138    * DLL
139    */
140   struct IdpClient *next;
141
142   /**
143    * The client
144    */
145   struct GNUNET_SERVICE_Client *client;
146
147   /**
148    * Message queue for transmission to @e client
149    */
150   struct GNUNET_MQ_Handle *mq;
151
152   /**
153    * Head of the DLL of
154    * Attribute iteration operations in
155    * progress initiated by this client
156    */
157   struct AttributeIterator *attr_iter_head;
158
159   /**
160    * Tail of the DLL of
161    * Attribute iteration operations
162    * in progress initiated by this client
163    */
164   struct AttributeIterator *attr_iter_tail;
165
166   /**
167    * Head of DLL of ticket iteration ops
168    */
169   struct TicketIteration *ticket_iter_head;
170
171   /**
172    * Tail of DLL of ticket iteration ops
173    */
174   struct TicketIteration *ticket_iter_tail;
175
176   /**
177    * Head of DLL of ticket revocation ops
178    */
179   struct TicketRevocationOperation *revoke_op_head;
180
181   /**
182    * Tail of DLL of ticket revocation ops
183    */
184   struct TicketRevocationOperation *revoke_op_tail;
185
186   /**
187    * Head of DLL of ticket issue ops
188    */
189   struct TicketIssueOperation *issue_op_head;
190
191   /**
192    * Tail of DLL of ticket issue ops
193    */
194   struct TicketIssueOperation *issue_op_tail;
195
196   /**
197    * Head of DLL of ticket consume ops
198    */
199   struct ConsumeTicketOperation *consume_op_head;
200
201   /**
202    * Tail of DLL of ticket consume ops
203    */
204   struct ConsumeTicketOperation *consume_op_tail;
205
206   /**
207    * Head of DLL of attribute store ops
208    */
209   struct AttributeStoreHandle *store_op_head;
210
211   /**
212    * Tail of DLL of attribute store ops
213    */
214   struct AttributeStoreHandle *store_op_tail;
215   /**
216    * Head of DLL of attribute delete ops
217    */
218   struct AttributeDeleteHandle *delete_op_head;
219
220   /**
221    * Tail of DLL of attribute delete ops
222    */
223   struct AttributeDeleteHandle *delete_op_tail;
224 };
225
226
227 /**
228  * Handle for attribute deletion request
229  */
230 struct AttributeDeleteHandle
231 {
232   /**
233    * DLL
234    */
235   struct AttributeDeleteHandle *next;
236
237   /**
238    * DLL
239    */
240   struct AttributeDeleteHandle *prev;
241
242   /**
243    * Client connection
244    */
245   struct IdpClient *client;
246
247   /**
248    * Identity
249    */
250   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
251
252
253   /**
254    * QueueEntry
255    */
256   struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
257
258   /**
259    * Iterator
260    */
261   struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
262
263   /**
264    * The attribute to delete
265    */
266   struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
267
268   /**
269    * Tickets to update
270    */
271   struct TicketRecordsEntry *tickets_to_update_head;
272
273   /**
274    * Tickets to update
275    */
276   struct TicketRecordsEntry *tickets_to_update_tail;
277
278   /**
279    * Attribute label
280    */
281   char *label;
282
283   /**
284    * request id
285    */
286   uint32_t r_id;
287 };
288
289
290 /**
291  * Handle for attribute store request
292  */
293 struct AttributeStoreHandle
294 {
295   /**
296    * DLL
297    */
298   struct AttributeStoreHandle *next;
299
300   /**
301    * DLL
302    */
303   struct AttributeStoreHandle *prev;
304
305   /**
306    * Client connection
307    */
308   struct IdpClient *client;
309
310   /**
311    * Identity
312    */
313   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
314
315   /**
316    * Identity pubkey
317    */
318   struct GNUNET_CRYPTO_EcdsaPublicKey identity_pkey;
319
320   /**
321    * QueueEntry
322    */
323   struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
324
325   /**
326    * The attribute to store
327    */
328   struct GNUNET_RECLAIM_ATTRIBUTE_Claim *claim;
329
330   /**
331    * The attribute expiration interval
332    */
333   struct GNUNET_TIME_Relative exp;
334
335   /**
336    * request id
337    */
338   uint32_t r_id;
339 };
340
341
342 /**
343  * Handle for ticket consume request
344  */
345 struct ConsumeTicketOperation
346 {
347   /**
348    * DLL
349    */
350   struct ConsumeTicketOperation *next;
351
352   /**
353    * DLL
354    */
355   struct ConsumeTicketOperation *prev;
356
357   /**
358    * Client connection
359    */
360   struct IdpClient *client;
361
362   /**
363    * request id
364    */
365   uint32_t r_id;
366
367   /**
368    * Ticket consume handle
369    */
370   struct RECLAIM_TICKETS_ConsumeHandle *ch;
371 };
372
373
374 /**
375  * Ticket revocation request handle
376  */
377 struct TicketRevocationOperation
378 {
379   /**
380    * DLL
381    */
382   struct TicketRevocationOperation *prev;
383
384   /**
385    * DLL
386    */
387   struct TicketRevocationOperation *next;
388
389   /**
390    * Client connection
391    */
392   struct IdpClient *client;
393
394   /**
395    * Revocation handle
396    */
397   struct RECLAIM_TICKETS_RevokeHandle *rh;
398
399   /**
400    * request id
401    */
402   uint32_t r_id;
403 };
404
405
406 /**
407  * Ticket issue operation handle
408  */
409 struct TicketIssueOperation
410 {
411   /**
412    * DLL
413    */
414   struct TicketIssueOperation *prev;
415
416   /**
417    * DLL
418    */
419   struct TicketIssueOperation *next;
420
421   /**
422    * Client connection
423    */
424   struct IdpClient *client;
425
426   /**
427    * request id
428    */
429   uint32_t r_id;
430 };
431
432
433 /**
434  * Client list
435  */
436 static struct IdpClient *client_list_head = NULL;
437
438 /**
439  * Client list
440  */
441 static struct IdpClient *client_list_tail = NULL;
442
443
444 /**
445  * Cleanup attribute delete handle
446  *
447  * @param adh the attribute to cleanup
448  */
449 static void
450 cleanup_adh (struct AttributeDeleteHandle *adh)
451 {
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,
464                                  le);
465     if (NULL != le->label)
466       GNUNET_free (le->label);
467     if (NULL != le->data)
468       GNUNET_free (le->data);
469     GNUNET_free (le);
470   }
471   GNUNET_free (adh);
472 }
473
474
475 /**
476  * Cleanup attribute store handle
477  *
478  * @param handle handle to clean up
479  */
480 static void
481 cleanup_as_handle (struct AttributeStoreHandle *ash)
482 {
483   if (NULL != ash->ns_qe)
484     GNUNET_NAMESTORE_cancel (ash->ns_qe);
485   if (NULL != ash->claim)
486     GNUNET_free (ash->claim);
487   GNUNET_free (ash);
488 }
489
490
491 /**
492  * Cleanup client
493  *
494  * @param idp the client to clean up
495  */
496 static void
497 cleanup_client (struct IdpClient *idp)
498 {
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;
506
507   while (NULL != (iss = idp->issue_op_head)) {
508     GNUNET_CONTAINER_DLL_remove (idp->issue_op_head, idp->issue_op_tail, iss);
509     GNUNET_free (iss);
510   }
511   while (NULL != (ct = idp->consume_op_head)) {
512     GNUNET_CONTAINER_DLL_remove (idp->consume_op_head,
513                                  idp->consume_op_tail,
514                                  ct);
515     if (NULL != ct->ch)
516       RECLAIM_TICKETS_consume_cancel (ct->ch);
517     GNUNET_free (ct);
518   }
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);
522   }
523   while (NULL != (adh = idp->delete_op_head)) {
524     GNUNET_CONTAINER_DLL_remove (idp->delete_op_head, idp->delete_op_tail, adh);
525     cleanup_adh (adh);
526   }
527
528   while (NULL != (ai = idp->attr_iter_head)) {
529     GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, idp->attr_iter_tail, ai);
530     GNUNET_free (ai);
531   }
532   while (NULL != (rop = idp->revoke_op_head)) {
533     GNUNET_CONTAINER_DLL_remove (idp->revoke_op_head, idp->revoke_op_tail, rop);
534     if (NULL != rop->rh)
535       RECLAIM_TICKETS_revoke_cancel (rop->rh);
536     GNUNET_free (rop);
537   }
538   while (NULL != (ti = idp->ticket_iter_head)) {
539     GNUNET_CONTAINER_DLL_remove (idp->ticket_iter_head,
540                                  idp->ticket_iter_tail,
541                                  ti);
542     if (NULL != ti->iter)
543       RECLAIM_TICKETS_iteration_stop (ti->iter);
544     GNUNET_free (ti);
545   }
546   GNUNET_free (idp);
547 }
548
549
550 /**
551  * Cleanup task
552  */
553 static void
554 cleanup ()
555 {
556   struct IdpClient *cl;
557   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
558
559   while (NULL != (cl = client_list_head))
560   {
561     GNUNET_CONTAINER_DLL_remove (client_list_head,
562                                  client_list_tail,
563                                  cl);
564     cleanup_client (cl);
565   }
566   RECLAIM_TICKETS_deinit ();
567   if (NULL != timeout_task)
568     GNUNET_SCHEDULER_cancel (timeout_task);
569   if (NULL != nsh)
570     GNUNET_NAMESTORE_disconnect (nsh);
571 }
572
573
574 /**
575  * Shutdown task
576  *
577  * @param cls NULL
578  */
579 static void
580 do_shutdown (void *cls)
581 {
582   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down...\n");
583   cleanup ();
584 }
585
586
587 /**
588  * Sends a ticket result message to the client
589  *
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
594  */
595 static void
596 send_ticket_result (const struct IdpClient *client,
597                     uint32_t r_id,
598                     const struct GNUNET_RECLAIM_Ticket *ticket,
599                     uint32_t success)
600 {
601   struct TicketResultMessage *irm;
602   struct GNUNET_MQ_Envelope *env;
603   struct GNUNET_RECLAIM_Ticket *ticket_buf;
604
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;
611   } else {
612     env = GNUNET_MQ_msg (irm, GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
613   }
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);
618 }
619
620
621 /**
622  * Issue ticket result
623  *
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)
628  */
629 static void
630 issue_ticket_result_cb (void *cls,
631                         struct GNUNET_RECLAIM_Ticket *ticket,
632                         int32_t success,
633                         const char *emsg)
634 {
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,
640                                  tio);
641     GNUNET_free (tio);
642     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error issuing ticket: %s\n", emsg);
643     return;
644   }
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,
648                                tio);
649   GNUNET_free (tio);
650 }
651
652
653 /**
654  * Check issue ticket message
655  *
656  * @cls unused
657  * @im message to check
658  * @return GNUNET_OK if message is ok
659  */
660 static int
661 check_issue_ticket_message (void *cls, const struct IssueTicketMessage *im)
662 {
663   uint16_t size;
664
665   size = ntohs (im->header.size);
666   if (size <= sizeof (struct IssueTicketMessage)) {
667     GNUNET_break (0);
668     return GNUNET_SYSERR;
669   }
670   return GNUNET_OK;
671 }
672
673
674 /**
675  * Handle ticket issue message
676  *
677  * @param cls our client
678  * @param im the message
679  */
680 static void
681 handle_issue_ticket_message (void *cls, const struct IssueTicketMessage *im)
682 {
683   struct TicketIssueOperation *tio;
684   struct IdpClient *idp = cls;
685   struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
686   size_t attrs_len;
687
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);
693   tio->client = idp;
694   GNUNET_CONTAINER_DLL_insert (idp->issue_op_head, idp->issue_op_tail, tio);
695   RECLAIM_TICKETS_issue (&im->identity,
696                          attrs,
697                          &im->rp,
698                          &issue_ticket_result_cb,
699                          tio);
700   GNUNET_SERVICE_client_continue (idp->client);
701   GNUNET_RECLAIM_ATTRIBUTE_list_destroy (attrs);
702 }
703
704
705
706 /**********************************************************
707  * Revocation
708  **********************************************************/
709
710 /**
711  * Handles revocation result
712  *
713  * @param cls our revocation operation handle
714  * @param success revocation result (GNUNET_OK if successful)
715  */
716 static void
717 revoke_result_cb (void *cls, int32_t success)
718 {
719   struct TicketRevocationOperation *rop = cls;
720   struct GNUNET_MQ_Envelope *env;
721   struct RevokeTicketResultMessage *trm;
722
723   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending REVOKE_TICKET_RESULT message\n");
724   rop->rh = NULL;
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,
731                                rop);
732   GNUNET_free (rop);
733 }
734
735
736 /**
737  * Check revocation message format
738  *
739  * @param cls unused
740  * @param im the message to check
741  * @return GNUNET_OK if message is ok
742  */
743 static int
744 check_revoke_ticket_message (void *cls, const struct RevokeTicketMessage *im)
745 {
746   uint16_t size;
747
748   size = ntohs (im->header.size);
749   if (size <= sizeof (struct RevokeTicketMessage)) {
750     GNUNET_break (0);
751     return GNUNET_SYSERR;
752   }
753   return GNUNET_OK;
754 }
755
756
757 /**
758  * Handle a revocation message to a ticket.
759  *
760  * @param cls our client
761  * @param rm the message to handle
762  */
763 static void
764 handle_revoke_ticket_message (void *cls, const struct RevokeTicketMessage *rm)
765 {
766   struct TicketRevocationOperation *rop;
767   struct IdpClient *idp = cls;
768   struct GNUNET_RECLAIM_Ticket *ticket;
769
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);
774   rop->client = idp;
775   GNUNET_CONTAINER_DLL_insert (idp->revoke_op_head, idp->revoke_op_tail, rop);
776   rop->rh
777     = RECLAIM_TICKETS_revoke (ticket, &rm->identity, &revoke_result_cb, rop);
778   GNUNET_SERVICE_client_continue (idp->client);
779 }
780
781
782 /**
783  * Handle a ticket consume result
784  *
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)
790  */
791 static void
792 consume_result_cb (void *cls,
793                    const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
794                    const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
795                    int32_t success,
796                    const char *emsg)
797 {
798   struct ConsumeTicketOperation *cop = cls;
799   struct ConsumeTicketResultMessage *crm;
800   struct GNUNET_MQ_Envelope *env;
801   char *data_tmp;
802   size_t attrs_len;
803   if (GNUNET_OK != success) {
804     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error consuming ticket: %s\n", emsg);
805   }
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,
809                              attrs_len,
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,
820                                cop);
821   GNUNET_free (cop);
822 }
823
824
825 /**
826  * Check a consume ticket message
827  *
828  * @param cls unused
829  * @param cm the message to handle
830  */
831 static int
832 check_consume_ticket_message (void *cls, const struct ConsumeTicketMessage *cm)
833 {
834   uint16_t size;
835
836   size = ntohs (cm->header.size);
837   if (size <= sizeof (struct ConsumeTicketMessage)) {
838     GNUNET_break (0);
839     return GNUNET_SYSERR;
840   }
841   return GNUNET_OK;
842 }
843
844
845 /**
846  * Handle a consume ticket message
847  *
848  * @param cls our client handle
849  * @cm the message to handle
850  */
851 static void
852 handle_consume_ticket_message (void *cls, const struct ConsumeTicketMessage *cm)
853 {
854   struct ConsumeTicketOperation *cop;
855   struct GNUNET_RECLAIM_Ticket *ticket;
856   struct IdpClient *idp = cls;
857
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);
861   cop->client = idp;
862   ticket = (struct GNUNET_RECLAIM_Ticket *)&cm[1];
863   cop->ch
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);
867 }
868
869 /*****************************************
870  * Attribute store
871  *****************************************/
872
873
874 /**
875  * Attribute store result handler
876  *
877  * @param cls our attribute store handle
878  * @param success GNUNET_OK if successful
879  * @param emsg error message (NULL if success=GNUNET_OK)
880  */
881 static void
882 attr_store_cont (void *cls, int32_t success, const char *emsg)
883 {
884   struct AttributeStoreHandle *ash = cls;
885   struct GNUNET_MQ_Envelope *env;
886   struct SuccessResultMessage *acr_msg;
887
888   ash->ns_qe = NULL;
889   GNUNET_CONTAINER_DLL_remove (ash->client->store_op_head,
890                                ash->client->store_op_tail,
891                                ash);
892
893   if (GNUNET_SYSERR == success) {
894     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
895                 "Failed to store attribute %s\n",
896                 emsg);
897     cleanup_as_handle (ash);
898     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
899     return;
900   }
901
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);
908 }
909
910
911 /**
912  * Add a new attribute
913  *
914  * @param cls the AttributeStoreHandle
915  */
916 static void
917 attr_store_task (void *cls)
918 {
919   struct AttributeStoreHandle *ash = cls;
920   struct GNUNET_GNSRECORD_Data rd[1];
921   char *buf;
922   char *label;
923   size_t buf_size;
924
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)
930     ash->claim->id
931       = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX);
932   GNUNET_RECLAIM_ATTRIBUTE_serialize (ash->claim, buf);
933   label
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);
936
937   rd[0].data_size = buf_size;
938   rd[0].data = buf;
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,
943                                                &ash->identity,
944                                                label,
945                                                1,
946                                                rd,
947                                                &attr_store_cont,
948                                                ash);
949   GNUNET_free (buf);
950 }
951
952
953 /**
954  * Check an attribute store message
955  *
956  * @param cls unused
957  * @param sam the message to check
958  */
959 static int
960 check_attribute_store_message (void *cls,
961                                const struct AttributeStoreMessage *sam)
962 {
963   uint16_t size;
964
965   size = ntohs (sam->header.size);
966   if (size <= sizeof (struct AttributeStoreMessage)) {
967     GNUNET_break (0);
968     return GNUNET_SYSERR;
969   }
970   return GNUNET_OK;
971 }
972
973
974 /**
975  * Handle an attribute store message
976  *
977  * @param cls our client
978  * @param sam the message to handle
979  */
980 static void
981 handle_attribute_store_message (void *cls,
982                                 const struct AttributeStoreMessage *sam)
983 {
984   struct AttributeStoreHandle *ash;
985   struct IdpClient *idp = cls;
986   size_t data_len;
987   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTRIBUTE_STORE message\n");
988
989   data_len = ntohs (sam->attr_len);
990
991   ash = GNUNET_new (struct AttributeStoreHandle);
992   ash->claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize ((char *)&sam[1], data_len);
993
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);
998
999   GNUNET_SERVICE_client_continue (idp->client);
1000   ash->client = idp;
1001   GNUNET_CONTAINER_DLL_insert (idp->store_op_head, idp->store_op_tail, ash);
1002   GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
1003 }
1004
1005
1006 /**
1007  * Send a deletion success response
1008  *
1009  * @param adh our attribute deletion handle
1010  * @param success the success status
1011  */
1012 static void
1013 send_delete_response (struct AttributeDeleteHandle *adh, int32_t success)
1014 {
1015   struct GNUNET_MQ_Envelope *env;
1016   struct SuccessResultMessage *acr_msg;
1017
1018   GNUNET_CONTAINER_DLL_remove (adh->client->delete_op_head,
1019                                adh->client->delete_op_tail,
1020                                adh);
1021
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);
1027 }
1028
1029
1030 /**
1031  * Namestore iteration within attribute deletion.
1032  * We need to reissue tickets with the deleted attribute removed.
1033  *
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
1039  */
1040 static void
1041 ticket_iter (void *cls,
1042              const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1043              const char *label,
1044              unsigned int rd_count,
1045              const struct GNUNET_GNSRECORD_Data *rd)
1046 {
1047   struct AttributeDeleteHandle *adh = cls;
1048   struct TicketRecordsEntry *le;
1049   int has_changed = GNUNET_NO;
1050
1051   for (int i = 0; i < rd_count; i++) {
1052     if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR_REF != rd[i].record_type)
1053       continue;
1054     if (0 != memcmp (rd[i].data, &adh->claim->id, sizeof (uint64_t)))
1055       continue;
1056     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1057                 "Attribute to delete found (%s)\n",
1058                 adh->label);
1059     has_changed = GNUNET_YES;
1060     break;
1061   }
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,
1071                                  le);
1072   }
1073   GNUNET_NAMESTORE_zone_iterator_next (adh->ns_it, 1);
1074 }
1075
1076
1077 /**
1078  * Recursion prototype for function
1079  * @param cls our deletion handle
1080  */
1081 static void
1082 update_tickets (void *cls);
1083
1084
1085 /**
1086  * Callback called when a ticket was updated
1087  *
1088  * @param cls our attribute deletion handle
1089  * @param success GNUNET_OK if successful
1090  * @param emsg error message (NULL if success=GNUNET_OK)
1091  */
1092 static void
1093 ticket_updated (void *cls, int32_t success, const char *emsg)
1094 {
1095   struct AttributeDeleteHandle *adh = cls;
1096   adh->ns_qe = NULL;
1097   GNUNET_SCHEDULER_add_now (&update_tickets, adh);
1098 }
1099
1100
1101 /**
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''.
1105  *
1106  * @param cls our attribute deletion handle
1107  */
1108 static void
1109 update_tickets (void *cls)
1110 {
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);
1117     cleanup_adh (adh);
1118     return;
1119   }
1120   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1121               "Updating %s\n",
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,
1126                                le);
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,
1130                                         le->data,
1131                                         le->rd_count,
1132                                         rd);
1133   int j = 0;
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))))
1137       continue;
1138     rd_new[j] = rd[i];
1139     j++;
1140   }
1141   adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1142                                                &adh->identity,
1143                                                le->label,
1144                                                j,
1145                                                rd_new,
1146                                                &ticket_updated,
1147                                                adh);
1148   GNUNET_free (le->label);
1149   GNUNET_free (le->data);
1150   GNUNET_free (le);
1151 }
1152
1153
1154 /**
1155  * Done collecting affected tickets, start updating.
1156  *
1157  * @param cls our attribute deletion handle
1158  */
1159 static void
1160 ticket_iter_fin (void *cls)
1161 {
1162   struct AttributeDeleteHandle *adh = cls;
1163   adh->ns_it = NULL;
1164   GNUNET_SCHEDULER_add_now (&update_tickets, adh);
1165 }
1166
1167
1168 /**
1169  * Error collecting affected tickets. Abort.
1170  *
1171  * @param cls our attribute deletion handle
1172  */
1173 static void
1174 ticket_iter_err (void *cls)
1175 {
1176   struct AttributeDeleteHandle *adh = cls;
1177   adh->ns_it = NULL;
1178   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1179               "Namestore error on delete %s\n",
1180               adh->label);
1181   send_delete_response (adh, GNUNET_SYSERR);
1182   cleanup_adh (adh);
1183 }
1184
1185
1186 /**
1187  * Start processing tickets which may still contain reference to deleted
1188  * attribute.
1189  *
1190  * @param cls attribute deletion handle
1191  */
1192 static void
1193 start_ticket_update (void *cls)
1194 {
1195   struct AttributeDeleteHandle *adh = cls;
1196   adh->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh,
1197                                                       &adh->identity,
1198                                                       &ticket_iter_err,
1199                                                       adh,
1200                                                       &ticket_iter,
1201                                                       adh,
1202                                                       &ticket_iter_fin,
1203                                                       adh);
1204 }
1205
1206
1207 /**
1208  * Attribute deleted callback
1209  *
1210  * @param cls our handle
1211  * @param success success status
1212  * @param emsg error message (NULL if success=GNUNET_OK)
1213  */
1214 static void
1215 attr_delete_cont (void *cls, int32_t success, const char *emsg)
1216 {
1217   struct AttributeDeleteHandle *adh = cls;
1218   adh->ns_qe = NULL;
1219   if (GNUNET_SYSERR == success) {
1220     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1221                 "Error deleting attribute %s\n",
1222                 adh->label);
1223     send_delete_response (adh, GNUNET_SYSERR);
1224     cleanup_adh (adh);
1225     return;
1226   }
1227   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating tickets...\n");
1228   GNUNET_SCHEDULER_add_now (&start_ticket_update, adh);
1229 }
1230
1231
1232 /**
1233  * Check attribute delete message format
1234  *
1235  * @cls unused
1236  * @dam message to check
1237  */
1238 static int
1239 check_attribute_delete_message (void *cls,
1240                                 const struct AttributeDeleteMessage *dam)
1241 {
1242   uint16_t size;
1243
1244   size = ntohs (dam->header.size);
1245   if (size <= sizeof (struct AttributeDeleteMessage)) {
1246     GNUNET_break (0);
1247     return GNUNET_SYSERR;
1248   }
1249   return GNUNET_OK;
1250 }
1251
1252
1253 /**
1254  * Handle attribute deletion
1255  *
1256  * @param cls our client
1257  * @param dam deletion message
1258  */
1259 static void
1260 handle_attribute_delete_message (void *cls,
1261                                  const struct AttributeDeleteMessage *dam)
1262 {
1263   struct AttributeDeleteHandle *adh;
1264   struct IdpClient *idp = cls;
1265   size_t data_len;
1266   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTRIBUTE_DELETE message\n");
1267
1268   data_len = ntohs (dam->attr_len);
1269
1270   adh = GNUNET_new (struct AttributeDeleteHandle);
1271   adh->claim = GNUNET_RECLAIM_ATTRIBUTE_deserialize ((char *)&dam[1], data_len);
1272
1273   adh->r_id = ntohl (dam->id);
1274   adh->identity = dam->identity;
1275   adh->label
1276     = GNUNET_STRINGS_data_to_string_alloc (&adh->claim->id, sizeof (uint64_t));
1277   GNUNET_SERVICE_client_continue (idp->client);
1278   adh->client = idp;
1279   GNUNET_CONTAINER_DLL_insert (idp->delete_op_head, idp->delete_op_tail, adh);
1280   adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1281                                                &adh->identity,
1282                                                adh->label,
1283                                                0,
1284                                                NULL,
1285                                                &attr_delete_cont,
1286                                                adh);
1287 }
1288
1289
1290 /*************************************************
1291  * Attrubute iteration
1292  *************************************************/
1293
1294
1295 /**
1296  * Done iterating over attributes
1297  *
1298  * @param cls our iterator handle
1299  */
1300 static void
1301 attr_iter_finished (void *cls)
1302 {
1303   struct AttributeIterator *ai = cls;
1304   struct GNUNET_MQ_Envelope *env;
1305   struct AttributeResultMessage *arm;
1306
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,
1314                                ai);
1315   GNUNET_free (ai);
1316 }
1317
1318 /**
1319  * Error iterating over attributes. Abort.
1320  *
1321  * @param cls our attribute iteration handle
1322  */
1323 static void
1324 attr_iter_error (void *cls)
1325 {
1326   struct AttributeIterator *ai = cls;
1327
1328   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to iterate over attributes\n");
1329   attr_iter_finished (ai);
1330 }
1331
1332
1333 /**
1334  * Got record. Return if it is an attribute.
1335  *
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
1340  * @param rd records
1341  */
1342 static void
1343 attr_iter_cb (void *cls,
1344               const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1345               const char *label,
1346               unsigned int rd_count,
1347               const struct GNUNET_GNSRECORD_Data *rd)
1348 {
1349   struct AttributeIterator *ai = cls;
1350   struct AttributeResultMessage *arm;
1351   struct GNUNET_MQ_Envelope *env;
1352   char *data_tmp;
1353
1354   if (rd_count != 1) {
1355     GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1356     return;
1357   }
1358
1359   if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTR != rd->record_type) {
1360     GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1361     return;
1362   }
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,
1366                              rd->data_size,
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);
1374 }
1375
1376
1377 /**
1378  * Iterate over zone to get attributes
1379  *
1380  * @param cls our client
1381  * @param ais_msg the iteration message to start
1382  */
1383 static void
1384 handle_iteration_start (void *cls,
1385                         const struct AttributeIterationStartMessage *ais_msg)
1386 {
1387   struct IdpClient *idp = cls;
1388   struct AttributeIterator *ai;
1389
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);
1394   ai->client = idp;
1395   ai->identity = ais_msg->identity;
1396
1397   GNUNET_CONTAINER_DLL_insert (idp->attr_iter_head, idp->attr_iter_tail, ai);
1398   ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh,
1399                                                      &ai->identity,
1400                                                      &attr_iter_error,
1401                                                      ai,
1402                                                      &attr_iter_cb,
1403                                                      ai,
1404                                                      &attr_iter_finished,
1405                                                      ai);
1406   GNUNET_SERVICE_client_continue (idp->client);
1407 }
1408
1409
1410 /**
1411  * Handle iteration stop message from client
1412  *
1413  * @param cls the client
1414  * @param ais_msg the stop message
1415  */
1416 static void
1417 handle_iteration_stop (void *cls,
1418                        const struct AttributeIterationStopMessage *ais_msg)
1419 {
1420   struct IdpClient *idp = cls;
1421   struct AttributeIterator *ai;
1422   uint32_t rid;
1423
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)
1430       break;
1431   if (NULL == ai) {
1432     GNUNET_break (0);
1433     GNUNET_SERVICE_client_drop (idp->client);
1434     return;
1435   }
1436   GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, idp->attr_iter_tail, ai);
1437   GNUNET_free (ai);
1438   GNUNET_SERVICE_client_continue (idp->client);
1439 }
1440
1441
1442 /**
1443  * Client requests next attribute from iterator
1444  *
1445  * @param cls the client
1446  * @param ais_msg the message
1447  */
1448 static void
1449 handle_iteration_next (void *cls,
1450                        const struct AttributeIterationNextMessage *ais_msg)
1451 {
1452   struct IdpClient *idp = cls;
1453   struct AttributeIterator *ai;
1454   uint32_t rid;
1455
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)
1461       break;
1462   if (NULL == ai) {
1463     GNUNET_break (0);
1464     GNUNET_SERVICE_client_drop (idp->client);
1465     return;
1466   }
1467   GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1468   GNUNET_SERVICE_client_continue (idp->client);
1469 }
1470
1471 /******************************************************
1472  * Ticket iteration
1473  ******************************************************/
1474
1475 /**
1476  * Got a ticket. Return to client
1477  *
1478  * @param cls our ticket iterator
1479  * @param ticket the ticket
1480  */
1481 static void
1482 ticket_iter_cb (void *cls, struct GNUNET_RECLAIM_Ticket *ticket)
1483 {
1484   struct TicketIteration *ti = cls;
1485   struct GNUNET_MQ_Envelope *env;
1486   struct TicketResultMessage *trm;
1487
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,
1493                                  ti);
1494   } else {
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));
1499   }
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);
1503   if (NULL == ticket)
1504     GNUNET_free (ti);
1505 }
1506
1507
1508 /**
1509  * Client requests a ticket iteration
1510  *
1511  * @param cls the client
1512  * @param tis_msg the iteration request message
1513  */
1514 static void
1515 handle_ticket_iteration_start (
1516                                void *cls,
1517                                const struct TicketIterationStartMessage *tis_msg)
1518 {
1519   struct IdpClient *client = cls;
1520   struct TicketIteration *ti;
1521
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;
1527
1528   GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
1529                                client->ticket_iter_tail,
1530                                ti);
1531   ti->iter
1532     = RECLAIM_TICKETS_iteration_start (&tis_msg->identity, &ticket_iter_cb, ti);
1533   GNUNET_SERVICE_client_continue (client->client);
1534 }
1535
1536
1537 /**
1538  * Client has had enough tickets
1539  *
1540  * @param cls the client
1541  * @param tis_msg the stop message
1542  */
1543 static void
1544 handle_ticket_iteration_stop (void *cls,
1545                               const struct TicketIterationStopMessage *tis_msg)
1546 {
1547   struct IdpClient *client = cls;
1548   struct TicketIteration *ti;
1549   uint32_t rid;
1550
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)
1557       break;
1558   if (NULL == ti) {
1559     GNUNET_break (0);
1560     GNUNET_SERVICE_client_drop (client->client);
1561     return;
1562   }
1563   RECLAIM_TICKETS_iteration_stop (ti->iter);
1564   GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
1565                                client->ticket_iter_tail,
1566                                ti);
1567   GNUNET_free (ti);
1568   GNUNET_SERVICE_client_continue (client->client);
1569 }
1570
1571
1572 /**
1573  * Client requests next result.
1574  *
1575  * @param cls the client
1576  * @param tis_msg the message
1577  */
1578 static void
1579 handle_ticket_iteration_next (void *cls,
1580                               const struct TicketIterationNextMessage *tis_msg)
1581 {
1582   struct IdpClient *client = cls;
1583   struct TicketIteration *ti;
1584   uint32_t rid;
1585
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)
1591       break;
1592   if (NULL == ti) {
1593     GNUNET_break (0);
1594     GNUNET_SERVICE_client_drop (client->client);
1595     return;
1596   }
1597   RECLAIM_TICKETS_iteration_next (ti->iter);
1598   GNUNET_SERVICE_client_continue (client->client);
1599 }
1600
1601
1602 /**
1603  * Main function that will be run
1604  *
1605  * @param cls closure
1606  * @param c the configuration used
1607  * @param server the service handle
1608  */
1609 static void
1610 run (void *cls,
1611      const struct GNUNET_CONFIGURATION_Handle *c,
1612      struct GNUNET_SERVICE_Handle *server)
1613 {
1614   cfg = c;
1615
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 ();
1620     return;
1621   }
1622   // Connect to identity and namestore services
1623   nsh = GNUNET_NAMESTORE_connect (cfg);
1624   if (NULL == nsh) {
1625     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
1626                          "error connecting to namestore");
1627   }
1628
1629   GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
1630 }
1631
1632
1633 /**
1634  * Called whenever a client is disconnected.
1635  *
1636  * @param cls closure
1637  * @param client identification of the client
1638  * @param app_ctx @a client
1639  */
1640 static void
1641 client_disconnect_cb (void *cls,
1642                       struct GNUNET_SERVICE_Client *client,
1643                       void *app_ctx)
1644 {
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,
1648                                client_list_tail,
1649                                idp);
1650   cleanup_client (idp);
1651 }
1652
1653
1654 /**
1655  * Add a client to our list of active clients.
1656  *
1657  * @param cls NULL
1658  * @param client client to add
1659  * @param mq message queue for @a client
1660  * @return internal namestore client structure for this client
1661  */
1662 static void *
1663 client_connect_cb (void *cls,
1664                    struct GNUNET_SERVICE_Client *client,
1665                    struct GNUNET_MQ_Handle *mq)
1666 {
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;
1671   idp->mq = mq;
1672   GNUNET_CONTAINER_DLL_insert (client_list_head,
1673                                client_list_tail,
1674                                idp);
1675   return idp;
1676 }
1677
1678
1679 /**
1680  * Define "main" method using service macro.
1681  */
1682 GNUNET_SERVICE_MAIN (
1683                      "reclaim",
1684                      GNUNET_SERVICE_OPTION_NONE,
1685                      &run,
1686                      &client_connect_cb,
1687                      &client_disconnect_cb,
1688                      NULL,
1689                      GNUNET_MQ_hd_var_size (attribute_store_message,
1690                                             GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE,
1691                                             struct AttributeStoreMessage,
1692                                             NULL),
1693                      GNUNET_MQ_hd_var_size (attribute_delete_message,
1694                                             GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_DELETE,
1695                                             struct AttributeDeleteMessage,
1696                                             NULL),
1697                      GNUNET_MQ_hd_fixed_size (
1698                                               iteration_start,
1699                                               GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_START,
1700                                               struct AttributeIterationStartMessage,
1701                                               NULL),
1702                      GNUNET_MQ_hd_fixed_size (iteration_next,
1703                                               GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT,
1704                                               struct AttributeIterationNextMessage,
1705                                               NULL),
1706                      GNUNET_MQ_hd_fixed_size (iteration_stop,
1707                                               GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP,
1708                                               struct AttributeIterationStopMessage,
1709                                               NULL),
1710                      GNUNET_MQ_hd_var_size (issue_ticket_message,
1711                                             GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET,
1712                                             struct IssueTicketMessage,
1713                                             NULL),
1714                      GNUNET_MQ_hd_var_size (consume_ticket_message,
1715                                             GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET,
1716                                             struct ConsumeTicketMessage,
1717                                             NULL),
1718                      GNUNET_MQ_hd_fixed_size (ticket_iteration_start,
1719                                               GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_START,
1720                                               struct TicketIterationStartMessage,
1721                                               NULL),
1722                      GNUNET_MQ_hd_fixed_size (ticket_iteration_next,
1723                                               GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_NEXT,
1724                                               struct TicketIterationNextMessage,
1725                                               NULL),
1726                      GNUNET_MQ_hd_fixed_size (ticket_iteration_stop,
1727                                               GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_STOP,
1728                                               struct TicketIterationStopMessage,
1729                                               NULL),
1730                      GNUNET_MQ_hd_var_size (revoke_ticket_message,
1731                                             GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET,
1732                                             struct RevokeTicketMessage,
1733                                             NULL),
1734                      GNUNET_MQ_handler_end ());
1735 /* end of gnunet-service-reclaim.c */