remove 'illegal' (non-reentrant) log logic from signal handler
[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_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 Iterator
94 {
95   /**
96    * Next element in the DLL
97    */
98   struct Iterator *next;
99
100   /**
101    * Previous element in the DLL
102    */
103   struct Iterator *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    * Context
127    */
128   void *ctx;
129 };
130
131
132 /**
133  * An idp client
134  */
135 struct IdpClient
136 {
137   /**
138    * DLL
139    */
140   struct IdpClient *prev;
141
142   /**
143    * DLL
144    */
145   struct IdpClient *next;
146
147   /**
148    * The client
149    */
150   struct GNUNET_SERVICE_Client *client;
151
152   /**
153    * Message queue for transmission to @e client
154    */
155   struct GNUNET_MQ_Handle *mq;
156
157   /**
158    * Head of the DLL of
159    * Attribute iteration operations in
160    * progress initiated by this client
161    */
162   struct Iterator *attr_iter_head;
163
164   /**
165    * Tail of the DLL of
166    * Attribute iteration operations
167    * in progress initiated by this client
168    */
169   struct Iterator *attr_iter_tail;
170
171   /**
172    * Head of the DLL of
173    * Attribute iteration operations in
174    * progress initiated by this client
175    */
176   struct Iterator *attest_iter_head;
177
178   /**
179    * Tail of the DLL of
180    * Attribute iteration operations
181    * in progress initiated by this client
182    */
183   struct Iterator *attest_iter_tail;
184
185   /**
186    * Head of DLL of ticket iteration ops
187    */
188   struct TicketIteration *ticket_iter_head;
189
190   /**
191    * Tail of DLL of ticket iteration ops
192    */
193   struct TicketIteration *ticket_iter_tail;
194
195   /**
196    * Head of DLL of ticket revocation ops
197    */
198   struct TicketRevocationOperation *revoke_op_head;
199
200   /**
201    * Tail of DLL of ticket revocation ops
202    */
203   struct TicketRevocationOperation *revoke_op_tail;
204
205   /**
206    * Head of DLL of ticket issue ops
207    */
208   struct TicketIssueOperation *issue_op_head;
209
210   /**
211    * Tail of DLL of ticket issue ops
212    */
213   struct TicketIssueOperation *issue_op_tail;
214
215   /**
216    * Head of DLL of ticket consume ops
217    */
218   struct ConsumeTicketOperation *consume_op_head;
219
220   /**
221    * Tail of DLL of ticket consume ops
222    */
223   struct ConsumeTicketOperation *consume_op_tail;
224
225   /**
226    * Head of DLL of attribute store ops
227    */
228   struct AttributeStoreHandle *store_op_head;
229
230   /**
231    * Tail of DLL of attribute store ops
232    */
233   struct AttributeStoreHandle *store_op_tail;
234   /**
235    * Head of DLL of attribute delete ops
236    */
237   struct AttributeDeleteHandle *delete_op_head;
238
239   /**
240    * Tail of DLL of attribute delete ops
241    */
242   struct AttributeDeleteHandle *delete_op_tail;
243 };
244
245
246 /**
247  * Handle for attribute deletion request
248  */
249 struct AttributeDeleteHandle
250 {
251   /**
252    * DLL
253    */
254   struct AttributeDeleteHandle *next;
255
256   /**
257    * DLL
258    */
259   struct AttributeDeleteHandle *prev;
260
261   /**
262    * Client connection
263    */
264   struct IdpClient *client;
265
266   /**
267    * Identity
268    */
269   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
270
271
272   /**
273    * QueueEntry
274    */
275   struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
276
277   /**
278    * Iterator
279    */
280   struct GNUNET_NAMESTORE_ZoneIterator *ns_it;
281
282   /**
283    * The attribute to delete
284    */
285   struct GNUNET_RECLAIM_Attribute *claim;
286
287   /**
288    * The attestation to delete
289    */
290   struct GNUNET_RECLAIM_Attestation *attest;
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 /**
315  * Handle for attribute store request
316  */
317 struct AttributeStoreHandle
318 {
319   /**
320    * DLL
321    */
322   struct AttributeStoreHandle *next;
323
324   /**
325    * DLL
326    */
327   struct AttributeStoreHandle *prev;
328
329   /**
330    * Client connection
331    */
332   struct IdpClient *client;
333
334   /**
335    * Identity
336    */
337   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
338
339   /**
340    * Identity pubkey
341    */
342   struct GNUNET_CRYPTO_EcdsaPublicKey identity_pkey;
343
344   /**
345    * QueueEntry
346    */
347   struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
348
349   /**
350    * The attribute to store
351    */
352   struct GNUNET_RECLAIM_Attribute *claim;
353
354   /**
355   * The attestation to store
356   */
357   struct GNUNET_RECLAIM_Attestation *attest;
358
359   /**
360    * The attribute expiration interval
361    */
362   struct GNUNET_TIME_Relative exp;
363
364   /**
365    * request id
366    */
367   uint32_t r_id;
368 };
369
370
371 /**
372  * Handle for ticket consume request
373  */
374 struct ConsumeTicketOperation
375 {
376   /**
377    * DLL
378    */
379   struct ConsumeTicketOperation *next;
380
381   /**
382    * DLL
383    */
384   struct ConsumeTicketOperation *prev;
385
386   /**
387    * Client connection
388    */
389   struct IdpClient *client;
390
391   /**
392    * request id
393    */
394   uint32_t r_id;
395
396   /**
397    * Ticket consume handle
398    */
399   struct RECLAIM_TICKETS_ConsumeHandle *ch;
400 };
401
402
403 /**
404  * Ticket revocation request handle
405  */
406 struct TicketRevocationOperation
407 {
408   /**
409    * DLL
410    */
411   struct TicketRevocationOperation *prev;
412
413   /**
414    * DLL
415    */
416   struct TicketRevocationOperation *next;
417
418   /**
419    * Client connection
420    */
421   struct IdpClient *client;
422
423   /**
424    * Revocation handle
425    */
426   struct RECLAIM_TICKETS_RevokeHandle *rh;
427
428   /**
429    * request id
430    */
431   uint32_t r_id;
432 };
433
434
435 /**
436  * Ticket issue operation handle
437  */
438 struct TicketIssueOperation
439 {
440   /**
441    * DLL
442    */
443   struct TicketIssueOperation *prev;
444
445   /**
446    * DLL
447    */
448   struct TicketIssueOperation *next;
449
450   /**
451    * Client connection
452    */
453   struct IdpClient *client;
454
455   /**
456    * request id
457    */
458   uint32_t r_id;
459 };
460
461
462 /**
463  * Client list
464  */
465 static struct IdpClient *client_list_head = NULL;
466
467 /**
468  * Client list
469  */
470 static struct IdpClient *client_list_tail = NULL;
471
472
473 /**
474  * Cleanup attribute delete handle
475  *
476  * @param adh the attribute to cleanup
477  */
478 static void
479 cleanup_adh (struct AttributeDeleteHandle *adh)
480 {
481   struct TicketRecordsEntry *le;
482
483   if (NULL != adh->ns_it)
484     GNUNET_NAMESTORE_zone_iteration_stop (adh->ns_it);
485   if (NULL != adh->ns_qe)
486     GNUNET_NAMESTORE_cancel (adh->ns_qe);
487   if (NULL != adh->label)
488     GNUNET_free (adh->label);
489   if (NULL != adh->claim)
490     GNUNET_free (adh->claim);
491   if (NULL != adh->attest)
492     GNUNET_free (adh->attest);
493   while (NULL != (le = adh->tickets_to_update_head))
494   {
495     GNUNET_CONTAINER_DLL_remove (adh->tickets_to_update_head,
496                                  adh->tickets_to_update_tail,
497                                  le);
498     if (NULL != le->label)
499       GNUNET_free (le->label);
500     if (NULL != le->data)
501       GNUNET_free (le->data);
502     GNUNET_free (le);
503   }
504   GNUNET_free (adh);
505 }
506
507
508 /**
509  * Cleanup attribute store handle
510  *
511  * @param handle handle to clean up
512  */
513 static void
514 cleanup_as_handle (struct AttributeStoreHandle *ash)
515 {
516   if (NULL != ash->ns_qe)
517     GNUNET_NAMESTORE_cancel (ash->ns_qe);
518   if (NULL != ash->claim)
519     GNUNET_free (ash->claim);
520   if (NULL != ash->attest)
521     GNUNET_free (ash->attest);
522   GNUNET_free (ash);
523 }
524
525
526 /**
527  * Cleanup client
528  *
529  * @param idp the client to clean up
530  */
531 static void
532 cleanup_client (struct IdpClient *idp)
533 {
534   struct Iterator *ai;
535   struct TicketIteration *ti;
536   struct TicketRevocationOperation *rop;
537   struct TicketIssueOperation *iss;
538   struct ConsumeTicketOperation *ct;
539   struct AttributeStoreHandle *as;
540   struct AttributeDeleteHandle *adh;
541
542   while (NULL != (iss = idp->issue_op_head))
543   {
544     GNUNET_CONTAINER_DLL_remove (idp->issue_op_head, idp->issue_op_tail, iss);
545     GNUNET_free (iss);
546   }
547   while (NULL != (ct = idp->consume_op_head))
548   {
549     GNUNET_CONTAINER_DLL_remove (idp->consume_op_head,
550                                  idp->consume_op_tail,
551                                  ct);
552     if (NULL != ct->ch)
553       RECLAIM_TICKETS_consume_cancel (ct->ch);
554     GNUNET_free (ct);
555   }
556   while (NULL != (as = idp->store_op_head))
557   {
558     GNUNET_CONTAINER_DLL_remove (idp->store_op_head, idp->store_op_tail, as);
559     cleanup_as_handle (as);
560   }
561   while (NULL != (adh = idp->delete_op_head))
562   {
563     GNUNET_CONTAINER_DLL_remove (idp->delete_op_head, idp->delete_op_tail, adh);
564     cleanup_adh (adh);
565   }
566
567   while (NULL != (ai = idp->attr_iter_head))
568   {
569     GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, idp->attr_iter_tail, ai);
570     GNUNET_free (ai);
571   }
572   while (NULL != (ai = idp->attest_iter_head))
573   {
574     GNUNET_CONTAINER_DLL_remove (idp->attest_iter_head, idp->attest_iter_tail,
575                                  ai);
576     GNUNET_free (ai);
577   }
578
579   while (NULL != (rop = idp->revoke_op_head))
580   {
581     GNUNET_CONTAINER_DLL_remove (idp->revoke_op_head, idp->revoke_op_tail, rop);
582     if (NULL != rop->rh)
583       RECLAIM_TICKETS_revoke_cancel (rop->rh);
584     GNUNET_free (rop);
585   }
586   while (NULL != (ti = idp->ticket_iter_head))
587   {
588     GNUNET_CONTAINER_DLL_remove (idp->ticket_iter_head,
589                                  idp->ticket_iter_tail,
590                                  ti);
591     if (NULL != ti->iter)
592       RECLAIM_TICKETS_iteration_stop (ti->iter);
593     GNUNET_free (ti);
594   }
595   GNUNET_free (idp);
596 }
597
598
599 /**
600  * Cleanup task
601  */
602 static void
603 cleanup ()
604 {
605   struct IdpClient *cl;
606
607   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
608
609   while (NULL != (cl = client_list_head))
610   {
611     GNUNET_CONTAINER_DLL_remove (client_list_head,
612                                  client_list_tail,
613                                  cl);
614     cleanup_client (cl);
615   }
616   RECLAIM_TICKETS_deinit ();
617   if (NULL != timeout_task)
618     GNUNET_SCHEDULER_cancel (timeout_task);
619   if (NULL != nsh)
620     GNUNET_NAMESTORE_disconnect (nsh);
621 }
622
623
624 /**
625  * Shutdown task
626  *
627  * @param cls NULL
628  */
629 static void
630 do_shutdown (void *cls)
631 {
632   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down...\n");
633   cleanup ();
634 }
635
636
637 /**
638  * Sends a ticket result message to the client
639  *
640  * @param client the client to send to
641  * @param r_id the request message ID to reply to
642  * @param ticket the ticket to include (may be NULL)
643  * @param success the success status of the request
644  */
645 static void
646 send_ticket_result (const struct IdpClient *client,
647                     uint32_t r_id,
648                     const struct GNUNET_RECLAIM_Ticket *ticket,
649                     uint32_t success)
650 {
651   struct TicketResultMessage *irm;
652   struct GNUNET_MQ_Envelope *env;
653
654   env = GNUNET_MQ_msg (irm,
655                        GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
656   if (NULL != ticket)
657   {
658     irm->ticket = *ticket;
659   }
660   // TODO add success member
661   irm->id = htonl (r_id);
662   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending TICKET_RESULT message\n");
663   GNUNET_MQ_send (client->mq, env);
664 }
665
666
667 /**
668  * Issue ticket result
669  *
670  * @param cls out ticket issue operation handle
671  * @param ticket the issued ticket
672  * @param success issue success status (GNUNET_OK if successful)
673  * @param emsg error message (NULL of success is GNUNET_OK)
674  */
675 static void
676 issue_ticket_result_cb (void *cls,
677                         struct GNUNET_RECLAIM_Ticket *ticket,
678                         int32_t success,
679                         const char *emsg)
680 {
681   struct TicketIssueOperation *tio = cls;
682
683   if (GNUNET_OK != success)
684   {
685     send_ticket_result (tio->client, tio->r_id, NULL, GNUNET_SYSERR);
686     GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head,
687                                  tio->client->issue_op_tail,
688                                  tio);
689     GNUNET_free (tio);
690     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error issuing ticket: %s\n", emsg);
691     return;
692   }
693   send_ticket_result (tio->client, tio->r_id, ticket, GNUNET_SYSERR);
694   GNUNET_CONTAINER_DLL_remove (tio->client->issue_op_head,
695                                tio->client->issue_op_tail,
696                                tio);
697   GNUNET_free (tio);
698 }
699
700
701 /**
702  * Check issue ticket message
703  *
704  * @cls unused
705  * @im message to check
706  * @return GNUNET_OK if message is ok
707  */
708 static int
709 check_issue_ticket_message (void *cls, const struct IssueTicketMessage *im)
710 {
711   uint16_t size;
712
713   size = ntohs (im->header.size);
714   if (size <= sizeof(struct IssueTicketMessage))
715   {
716     GNUNET_break (0);
717     return GNUNET_SYSERR;
718   }
719   return GNUNET_OK;
720 }
721
722
723 /**
724  * Handle ticket issue message
725  *
726  * @param cls our client
727  * @param im the message
728  */
729 static void
730 handle_issue_ticket_message (void *cls, const struct IssueTicketMessage *im)
731 {
732   struct TicketIssueOperation *tio;
733   struct IdpClient *idp = cls;
734   struct GNUNET_RECLAIM_AttributeList *attrs;
735   size_t attrs_len;
736
737   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ISSUE_TICKET message\n");
738   tio = GNUNET_new (struct TicketIssueOperation);
739   attrs_len = ntohs (im->attr_len);
740   attrs = GNUNET_RECLAIM_attribute_list_deserialize ((char *) &im[1],
741                                                      attrs_len);
742   tio->r_id = ntohl (im->id);
743   tio->client = idp;
744   GNUNET_CONTAINER_DLL_insert (idp->issue_op_head, idp->issue_op_tail, tio);
745   RECLAIM_TICKETS_issue (&im->identity,
746                          attrs,
747                          &im->rp,
748                          &issue_ticket_result_cb,
749                          tio);
750   GNUNET_SERVICE_client_continue (idp->client);
751   GNUNET_RECLAIM_attribute_list_destroy (attrs);
752 }
753
754
755 /**********************************************************
756 * Revocation
757 **********************************************************/
758
759 /**
760  * Handles revocation result
761  *
762  * @param cls our revocation operation handle
763  * @param success revocation result (GNUNET_OK if successful)
764  */
765 static void
766 revoke_result_cb (void *cls, int32_t success)
767 {
768   struct TicketRevocationOperation *rop = cls;
769   struct GNUNET_MQ_Envelope *env;
770   struct RevokeTicketResultMessage *trm;
771
772   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
773               "Sending REVOKE_TICKET_RESULT message\n");
774   rop->rh = NULL;
775   env = GNUNET_MQ_msg (trm, GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT);
776   trm->id = htonl (rop->r_id);
777   trm->success = htonl (success);
778   GNUNET_MQ_send (rop->client->mq, env);
779   GNUNET_CONTAINER_DLL_remove (rop->client->revoke_op_head,
780                                rop->client->revoke_op_tail,
781                                rop);
782   GNUNET_free (rop);
783 }
784
785
786 /**
787  * Check revocation message format
788  *
789  * @param cls unused
790  * @param im the message to check
791  * @return GNUNET_OK if message is ok
792  */
793 static int
794 check_revoke_ticket_message (void *cls, const struct RevokeTicketMessage *im)
795 {
796   uint16_t size;
797
798   size = ntohs (im->header.size);
799   if (size != sizeof(struct RevokeTicketMessage))
800   {
801     GNUNET_break (0);
802     return GNUNET_SYSERR;
803   }
804   return GNUNET_OK;
805 }
806
807
808 /**
809  * Handle a revocation message to a ticket.
810  *
811  * @param cls our client
812  * @param rm the message to handle
813  */
814 static void
815 handle_revoke_ticket_message (void *cls, const struct RevokeTicketMessage *rm)
816 {
817   struct TicketRevocationOperation *rop;
818   struct IdpClient *idp = cls;
819
820   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received REVOKE_TICKET message\n");
821   rop = GNUNET_new (struct TicketRevocationOperation);
822   rop->r_id = ntohl (rm->id);
823   rop->client = idp;
824   GNUNET_CONTAINER_DLL_insert (idp->revoke_op_head, idp->revoke_op_tail, rop);
825   rop->rh
826     = RECLAIM_TICKETS_revoke (&rm->ticket, &rm->identity, &revoke_result_cb,
827                               rop);
828   GNUNET_SERVICE_client_continue (idp->client);
829 }
830
831
832 /**
833  * Handle a ticket consume result
834  *
835  * @param cls our consume ticket operation handle
836  * @param identity the attribute authority
837  * @param attrs the attribute/claim list
838  * @param success GNUNET_OK if successful
839  * @param emsg error message (NULL if success=GNUNET_OK)
840  */
841 static void
842 consume_result_cb (void *cls,
843                    const struct GNUNET_CRYPTO_EcdsaPublicKey *identity,
844                    const struct GNUNET_RECLAIM_AttributeList *attrs,
845                    const struct GNUNET_RECLAIM_AttestationList *attests,
846                    int32_t success,
847                    const char *emsg)
848 {
849   struct ConsumeTicketOperation *cop = cls;
850   struct ConsumeTicketResultMessage *crm;
851   struct GNUNET_MQ_Envelope *env;
852   char *data_tmp;
853   size_t attrs_len;
854   size_t attests_len;
855
856   if (GNUNET_OK != success)
857   {
858     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error consuming ticket: %s\n", emsg);
859   }
860   attrs_len = GNUNET_RECLAIM_attribute_list_serialize_get_size (attrs);
861   attests_len = GNUNET_RECLAIM_attestation_list_serialize_get_size (attests);
862   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
863               "Sending CONSUME_TICKET_RESULT message\n");
864   env = GNUNET_MQ_msg_extra (crm,
865                              attrs_len + attests_len,
866                              GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT);
867   crm->id = htonl (cop->r_id);
868   crm->attrs_len = htons (attrs_len);
869   crm->attestations_len = htons (attests_len);
870   crm->identity = *identity;
871   crm->result = htonl (success);
872   data_tmp = (char *) &crm[1];
873   GNUNET_RECLAIM_attribute_list_serialize (attrs, data_tmp);
874   data_tmp += attrs_len;
875   GNUNET_RECLAIM_attestation_list_serialize (attests, data_tmp);
876   GNUNET_MQ_send (cop->client->mq, env);
877   GNUNET_CONTAINER_DLL_remove (cop->client->consume_op_head,
878                                cop->client->consume_op_tail,
879                                cop);
880   GNUNET_free (cop);
881 }
882
883
884 /**
885  * Check a consume ticket message
886  *
887  * @param cls unused
888  * @param cm the message to handle
889  */
890 static int
891 check_consume_ticket_message (void *cls, const struct ConsumeTicketMessage *cm)
892 {
893   uint16_t size;
894
895   size = ntohs (cm->header.size);
896   if (size != sizeof(struct ConsumeTicketMessage))
897   {
898     GNUNET_break (0);
899     return GNUNET_SYSERR;
900   }
901   return GNUNET_OK;
902 }
903
904
905 /**
906  * Handle a consume ticket message
907  *
908  * @param cls our client handle
909  * @cm the message to handle
910  */
911 static void
912 handle_consume_ticket_message (void *cls, const struct ConsumeTicketMessage *cm)
913 {
914   struct ConsumeTicketOperation *cop;
915   struct IdpClient *idp = cls;
916
917   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received CONSUME_TICKET message\n");
918   cop = GNUNET_new (struct ConsumeTicketOperation);
919   cop->r_id = ntohl (cm->id);
920   cop->client = idp;
921   cop->ch
922     = RECLAIM_TICKETS_consume (&cm->identity, &cm->ticket, &consume_result_cb,
923                                cop);
924   GNUNET_CONTAINER_DLL_insert (idp->consume_op_head, idp->consume_op_tail, cop);
925   GNUNET_SERVICE_client_continue (idp->client);
926 }
927
928
929 /*****************************************
930 * Attribute store
931 *****************************************/
932
933
934 /**
935  * Attribute store result handler
936  *
937  * @param cls our attribute store handle
938  * @param success GNUNET_OK if successful
939  * @param emsg error message (NULL if success=GNUNET_OK)
940  */
941 static void
942 attr_store_cont (void *cls, int32_t success, const char *emsg)
943 {
944   struct AttributeStoreHandle *ash = cls;
945   struct GNUNET_MQ_Envelope *env;
946   struct SuccessResultMessage *acr_msg;
947
948   ash->ns_qe = NULL;
949   GNUNET_CONTAINER_DLL_remove (ash->client->store_op_head,
950                                ash->client->store_op_tail,
951                                ash);
952
953   if (GNUNET_SYSERR == success)
954   {
955     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
956                 "Failed to store attribute %s\n",
957                 emsg);
958     cleanup_as_handle (ash);
959     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
960     return;
961   }
962
963   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
964   env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
965   acr_msg->id = htonl (ash->r_id);
966   acr_msg->op_result = htonl (GNUNET_OK);
967   GNUNET_MQ_send (ash->client->mq, env);
968   cleanup_as_handle (ash);
969 }
970
971
972 /**
973  * Add a new attribute
974  *
975  * @param cls the AttributeStoreHandle
976  */
977 static void
978 attr_store_task (void *cls)
979 {
980   struct AttributeStoreHandle *ash = cls;
981   struct GNUNET_GNSRECORD_Data rd[1];
982   char *buf;
983   char *label;
984   size_t buf_size;
985
986   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Storing attribute\n");
987   buf_size = GNUNET_RECLAIM_attribute_serialize_get_size (ash->claim);
988   buf = GNUNET_malloc (buf_size);
989   // Give the ash a new id if unset
990   if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&ash->claim->id))
991     GNUNET_RECLAIM_id_generate (&ash->claim->id);
992   GNUNET_RECLAIM_attribute_serialize (ash->claim, buf);
993   label
994     = GNUNET_STRINGS_data_to_string_alloc (&ash->claim->id,
995                                            sizeof (ash->claim->id));
996   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting with label %s\n", label);
997
998   rd[0].data_size = buf_size;
999   rd[0].data = buf;
1000   rd[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE;
1001   rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1002   rd[0].expiration_time = ash->exp.rel_value_us;
1003   ash->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1004                                                &ash->identity,
1005                                                label,
1006                                                1,
1007                                                rd,
1008                                                &attr_store_cont,
1009                                                ash);
1010   GNUNET_free (buf);
1011   GNUNET_free (label);
1012 }
1013
1014
1015 /**
1016  * Check an attribute store message
1017  *
1018  * @param cls unused
1019  * @param sam the message to check
1020  */
1021 static int
1022 check_attribute_store_message (void *cls,
1023                                const struct AttributeStoreMessage *sam)
1024 {
1025   uint16_t size;
1026
1027   size = ntohs (sam->header.size);
1028   if (size <= sizeof(struct AttributeStoreMessage))
1029   {
1030     GNUNET_break (0);
1031     return GNUNET_SYSERR;
1032   }
1033   return GNUNET_OK;
1034 }
1035
1036
1037 /**
1038  * Handle an attribute store message
1039  *
1040  * @param cls our client
1041  * @param sam the message to handle
1042  */
1043 static void
1044 handle_attribute_store_message (void *cls,
1045                                 const struct AttributeStoreMessage *sam)
1046 {
1047   struct AttributeStoreHandle *ash;
1048   struct IdpClient *idp = cls;
1049   size_t data_len;
1050
1051   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTRIBUTE_STORE message\n");
1052
1053   data_len = ntohs (sam->attr_len);
1054
1055   ash = GNUNET_new (struct AttributeStoreHandle);
1056   ash->claim = GNUNET_RECLAIM_attribute_deserialize ((char *) &sam[1],
1057                                                      data_len);
1058
1059   ash->r_id = ntohl (sam->id);
1060   ash->identity = sam->identity;
1061   ash->exp.rel_value_us = GNUNET_ntohll (sam->exp);
1062   GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity, &ash->identity_pkey);
1063
1064   GNUNET_SERVICE_client_continue (idp->client);
1065   ash->client = idp;
1066   GNUNET_CONTAINER_DLL_insert (idp->store_op_head, idp->store_op_tail, ash);
1067   GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
1068 }
1069
1070
1071 /**
1072  * Attestation store result handler
1073  *
1074  * @param cls our attribute store handle
1075  * @param success GNUNET_OK if successful
1076  * @param emsg error message (NULL if success=GNUNET_OK)
1077  */
1078 static void
1079 attest_store_cont (void *cls, int32_t success, const char *emsg)
1080 {
1081   struct AttributeStoreHandle *ash = cls;
1082   struct GNUNET_MQ_Envelope *env;
1083   struct SuccessResultMessage *acr_msg;
1084
1085   ash->ns_qe = NULL;
1086   GNUNET_CONTAINER_DLL_remove (ash->client->store_op_head,
1087                                ash->client->store_op_tail,
1088                                ash);
1089
1090   if (GNUNET_SYSERR == success)
1091   {
1092     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1093                 "Failed to store attestation %s\n",
1094                 emsg);
1095     cleanup_as_handle (ash);
1096     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1097     return;
1098   }
1099
1100   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
1101   env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
1102   acr_msg->id = htonl (ash->r_id);
1103   acr_msg->op_result = htonl (GNUNET_OK);
1104   GNUNET_MQ_send (ash->client->mq, env);
1105   cleanup_as_handle (ash);
1106 }
1107
1108
1109 /**
1110  * Error looking up potential attestation. Abort.
1111  *
1112  * @param cls our attribute store handle
1113  */
1114 static void
1115 attest_error (void *cls)
1116 {
1117   struct AttributeStoreHandle *ash = cls;
1118   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1119               "Failed to check for existing Attestation\n");
1120   cleanup_as_handle (ash);
1121   GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1122   return;
1123 }
1124
1125
1126 /**
1127 * Check for existing record before storing attestation
1128 *
1129 * @param cls our attribute store handle
1130 * @param zone zone we are iterating
1131 * @param label label of the records
1132 * @param rd_count record count
1133 * @param rd records
1134 */
1135 static void
1136 attest_add_cb (void *cls,
1137                const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1138                const char *label,
1139                unsigned int rd_count,
1140                const struct GNUNET_GNSRECORD_Data *rd)
1141 {
1142   struct AttributeStoreHandle *ash = cls;
1143   char *buf;
1144   size_t buf_size;
1145   buf_size = GNUNET_RECLAIM_attestation_serialize_get_size (ash->attest);
1146   buf = GNUNET_malloc (buf_size);
1147   GNUNET_RECLAIM_attestation_serialize (ash->attest, buf);
1148   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1149               "Storing new Attestation\n");
1150   struct GNUNET_GNSRECORD_Data rd_new[1];
1151   rd_new[0].data_size = buf_size;
1152   rd_new[0].data = buf;
1153   rd_new[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION;
1154   rd_new[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1155   rd_new[0].expiration_time = ash->exp.rel_value_us;
1156   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting with label %s\n", label);
1157   ash->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1158                                                &ash->identity,
1159                                                label,
1160                                                1,
1161                                                rd_new,
1162                                                &attest_store_cont,
1163                                                ash);
1164   GNUNET_free (buf);
1165   return;
1166 }
1167
1168
1169 /**
1170  * Add a new attestation
1171  *
1172  * @param cls the AttributeStoreHandle
1173  */
1174 static void
1175 attest_store_task (void *cls)
1176 {
1177   struct AttributeStoreHandle *ash = cls;
1178   char *label;
1179
1180   // Give the ash a new id if unset
1181   if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&ash->attest->id))
1182     GNUNET_RECLAIM_id_generate (&ash->attest->id);
1183   label = GNUNET_STRINGS_data_to_string_alloc (&ash->attest->id,
1184                                                sizeof (ash->attest->id));
1185   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1186               "Looking up existing data under label %s\n", label);
1187 // Test for the content of the existing ID
1188   ash->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh,
1189                                                 &ash->identity,
1190                                                 label,
1191                                                 &attest_error,
1192                                                 ash,
1193                                                 &attest_add_cb,
1194                                                 ash);
1195   GNUNET_free (label);
1196 }
1197
1198
1199 /**
1200  * Check an attestation store message
1201  *
1202  * @param cls unused
1203  * @param sam the message to check
1204  */
1205 static int
1206 check_attestation_store_message (void *cls,
1207                                  const struct AttributeStoreMessage *sam)
1208 {
1209   uint16_t size;
1210
1211   size = ntohs (sam->header.size);
1212   if (size <= sizeof(struct AttributeStoreMessage))
1213   {
1214     GNUNET_break (0);
1215     return GNUNET_SYSERR;
1216   }
1217   return GNUNET_OK;
1218 }
1219
1220
1221 /**
1222 * Handle an attestation store message
1223 *
1224 * @param cls our client
1225 * @param sam the message to handle
1226 */
1227 static void
1228 handle_attestation_store_message (void *cls,
1229                                   const struct AttributeStoreMessage *sam)
1230 {
1231   struct AttributeStoreHandle *ash;
1232   struct IdpClient *idp = cls;
1233   size_t data_len;
1234
1235   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTESTATION_STORE message\n");
1236
1237   data_len = ntohs (sam->attr_len);
1238
1239   ash = GNUNET_new (struct AttributeStoreHandle);
1240   ash->attest = GNUNET_RECLAIM_attestation_deserialize ((char *) &sam[1],
1241                                                         data_len);
1242
1243   ash->r_id = ntohl (sam->id);
1244   ash->identity = sam->identity;
1245   ash->exp.rel_value_us = GNUNET_ntohll (sam->exp);
1246   GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity, &ash->identity_pkey);
1247
1248   GNUNET_SERVICE_client_continue (idp->client);
1249   ash->client = idp;
1250   GNUNET_CONTAINER_DLL_insert (idp->store_op_head, idp->store_op_tail, ash);
1251   GNUNET_SCHEDULER_add_now (&attest_store_task, ash);
1252 }
1253
1254
1255 /**
1256  * Send a deletion success response
1257  *
1258  * @param adh our attribute deletion handle
1259  * @param success the success status
1260  */
1261 static void
1262 send_delete_response (struct AttributeDeleteHandle *adh, int32_t success)
1263 {
1264   struct GNUNET_MQ_Envelope *env;
1265   struct SuccessResultMessage *acr_msg;
1266
1267   GNUNET_CONTAINER_DLL_remove (adh->client->delete_op_head,
1268                                adh->client->delete_op_tail,
1269                                adh);
1270
1271   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
1272   env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
1273   acr_msg->id = htonl (adh->r_id);
1274   acr_msg->op_result = htonl (success);
1275   GNUNET_MQ_send (adh->client->mq, env);
1276 }
1277
1278
1279 /**
1280  * Namestore iteration within attribute deletion.
1281  * We need to reissue tickets with the deleted attribute removed.
1282  *
1283  * @param cls our attribute deletion handle
1284  * @param zone the private key of the ticket issuer
1285  * @param label the label of the record
1286  * @param rd_count number of records
1287  * @param rd record data
1288  */
1289 static void
1290 ticket_iter (void *cls,
1291              const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1292              const char *label,
1293              unsigned int rd_count,
1294              const struct GNUNET_GNSRECORD_Data *rd)
1295 {
1296   struct AttributeDeleteHandle *adh = cls;
1297   struct TicketRecordsEntry *le;
1298   int has_changed = GNUNET_NO;
1299   for (int i = 0; i < rd_count; i++)
1300   {
1301     if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF != rd[i].record_type)
1302       continue;
1303     if (adh->claim != NULL)
1304       if (GNUNET_YES != GNUNET_RECLAIM_id_is_equal (rd[i].data,
1305                                                     &adh->claim->id))
1306         continue;
1307     if (adh->attest != NULL)
1308       if (GNUNET_YES != GNUNET_RECLAIM_id_is_equal (rd[i].data,
1309                                                     &adh->attest->id))
1310         continue;
1311     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1312                 "Attribute or Attestation to delete found (%s)\n",
1313                 adh->label);
1314     has_changed = GNUNET_YES;
1315     break;
1316   }
1317   if (GNUNET_YES == has_changed)
1318   {
1319     le = GNUNET_new (struct TicketRecordsEntry);
1320     le->data_size = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
1321     le->data = GNUNET_malloc (le->data_size);
1322     le->rd_count = rd_count;
1323     le->label = GNUNET_strdup (label);
1324     GNUNET_GNSRECORD_records_serialize (rd_count, rd, le->data_size, le->data);
1325     GNUNET_CONTAINER_DLL_insert (adh->tickets_to_update_head,
1326                                  adh->tickets_to_update_tail,
1327                                  le);
1328   }
1329   GNUNET_NAMESTORE_zone_iterator_next (adh->ns_it, 1);
1330 }
1331
1332
1333 /**
1334  * Recursion prototype for function
1335  * @param cls our deletion handle
1336  */
1337 static void
1338 update_tickets (void *cls);
1339
1340
1341 /**
1342  * Callback called when a ticket was updated
1343  *
1344  * @param cls our attribute deletion handle
1345  * @param success GNUNET_OK if successful
1346  * @param emsg error message (NULL if success=GNUNET_OK)
1347  */
1348 static void
1349 ticket_updated (void *cls, int32_t success, const char *emsg)
1350 {
1351   struct AttributeDeleteHandle *adh = cls;
1352
1353   adh->ns_qe = NULL;
1354   GNUNET_SCHEDULER_add_now (&update_tickets, adh);
1355 }
1356
1357
1358 /**
1359  * Update tickets: Remove shared attribute which has just been deleted.
1360  * This method is called recursively until all tickets are processed.
1361  * Eventually, the updated tickets are stored using ``update_tickets''.
1362  *
1363  * @param cls our attribute deletion handle
1364  */
1365 static void
1366 update_tickets (void *cls)
1367 {
1368   struct AttributeDeleteHandle *adh = cls;
1369   struct TicketRecordsEntry *le;
1370
1371   if (NULL == adh->tickets_to_update_head)
1372   {
1373     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1374                 "Finished updating tickets, success\n");
1375     send_delete_response (adh, GNUNET_OK);
1376     cleanup_adh (adh);
1377     return;
1378   }
1379   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1380               "Updating %s\n",
1381               adh->tickets_to_update_head->label);
1382   le = adh->tickets_to_update_head;
1383   GNUNET_CONTAINER_DLL_remove (adh->tickets_to_update_head,
1384                                adh->tickets_to_update_tail,
1385                                le);
1386   struct GNUNET_GNSRECORD_Data rd[le->rd_count];
1387   struct GNUNET_GNSRECORD_Data rd_new[le->rd_count - 1];
1388   if (GNUNET_OK != GNUNET_GNSRECORD_records_deserialize (le->data_size,
1389                                                          le->data,
1390                                                          le->rd_count,
1391                                                          rd))
1392   {
1393     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1394                 "Unable to deserialize record data!\n");
1395     send_delete_response (adh, GNUNET_SYSERR);
1396     cleanup_adh (adh);
1397     return;
1398   }
1399   int j = 0;
1400   for (int i = 0; i < le->rd_count; i++)
1401   {
1402     if (adh->claim != NULL)
1403       if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF == rd[i].record_type)
1404           && (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (rd[i].data,
1405                                                         &adh->claim->id)))
1406         continue;
1407     if (adh->attest != NULL)
1408       if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF == rd[i].record_type)
1409           && (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (rd[i].data,
1410                                                         &adh->attest->id)))
1411         continue;
1412     rd_new[j] = rd[i];
1413     j++;
1414   }
1415   adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1416                                                &adh->identity,
1417                                                le->label,
1418                                                j,
1419                                                rd_new,
1420                                                &ticket_updated,
1421                                                adh);
1422   GNUNET_free (le->label);
1423   GNUNET_free (le->data);
1424   GNUNET_free (le);
1425 }
1426
1427
1428 /**
1429  * Done collecting affected tickets, start updating.
1430  *
1431  * @param cls our attribute deletion handle
1432  */
1433 static void
1434 ticket_iter_fin (void *cls)
1435 {
1436   struct AttributeDeleteHandle *adh = cls;
1437   adh->ns_it = NULL;
1438   GNUNET_SCHEDULER_add_now (&update_tickets, adh);
1439 }
1440
1441
1442 /**
1443  * Error collecting affected tickets. Abort.
1444  *
1445  * @param cls our attribute deletion handle
1446  */
1447 static void
1448 ticket_iter_err (void *cls)
1449 {
1450   struct AttributeDeleteHandle *adh = cls;
1451
1452   adh->ns_it = NULL;
1453   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1454               "Namestore error on delete %s\n",
1455               adh->label);
1456   send_delete_response (adh, GNUNET_SYSERR);
1457   cleanup_adh (adh);
1458 }
1459
1460
1461 /**
1462  * Start processing tickets which may still contain reference to deleted
1463  * attribute.
1464  *
1465  * @param cls attribute deletion handle
1466  */
1467 static void
1468 start_ticket_update (void *cls)
1469 {
1470   struct AttributeDeleteHandle *adh = cls;
1471
1472   adh->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh,
1473                                                       &adh->identity,
1474                                                       &ticket_iter_err,
1475                                                       adh,
1476                                                       &ticket_iter,
1477                                                       adh,
1478                                                       &ticket_iter_fin,
1479                                                       adh);
1480 }
1481
1482
1483 /**
1484  * Attribute deleted callback
1485  *
1486  * @param cls our handle
1487  * @param success success status
1488  * @param emsg error message (NULL if success=GNUNET_OK)
1489  */
1490 static void
1491 attr_delete_cont (void *cls, int32_t success, const char *emsg)
1492 {
1493   struct AttributeDeleteHandle *adh = cls;
1494
1495   adh->ns_qe = NULL;
1496   if (GNUNET_SYSERR == success)
1497   {
1498     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1499                 "Error deleting attribute %s\n",
1500                 adh->label);
1501     send_delete_response (adh, GNUNET_SYSERR);
1502     cleanup_adh (adh);
1503     return;
1504   }
1505   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating tickets...\n");
1506   GNUNET_SCHEDULER_add_now (&start_ticket_update, adh);
1507 }
1508
1509
1510 /**
1511  * Check attribute delete message format
1512  *
1513  * @cls unused
1514  * @dam message to check
1515  */
1516 static int
1517 check_attribute_delete_message (void *cls,
1518                                 const struct AttributeDeleteMessage *dam)
1519 {
1520   uint16_t size;
1521
1522   size = ntohs (dam->header.size);
1523   if (size <= sizeof(struct AttributeDeleteMessage))
1524   {
1525     GNUNET_break (0);
1526     return GNUNET_SYSERR;
1527   }
1528   return GNUNET_OK;
1529 }
1530
1531
1532 /**
1533  * Handle attribute deletion
1534  *
1535  * @param cls our client
1536  * @param dam deletion message
1537  */
1538 static void
1539 handle_attribute_delete_message (void *cls,
1540                                  const struct AttributeDeleteMessage *dam)
1541 {
1542   struct AttributeDeleteHandle *adh;
1543   struct IdpClient *idp = cls;
1544   size_t data_len;
1545
1546   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTRIBUTE_DELETE message\n");
1547
1548   data_len = ntohs (dam->attr_len);
1549
1550   adh = GNUNET_new (struct AttributeDeleteHandle);
1551   adh->claim = GNUNET_RECLAIM_attribute_deserialize ((char *) &dam[1],
1552                                                      data_len);
1553   adh->attest = NULL;
1554
1555   adh->r_id = ntohl (dam->id);
1556   adh->identity = dam->identity;
1557   adh->label
1558     = GNUNET_STRINGS_data_to_string_alloc (&adh->claim->id,
1559                                            sizeof(adh->claim->id));
1560   GNUNET_SERVICE_client_continue (idp->client);
1561   adh->client = idp;
1562   GNUNET_CONTAINER_DLL_insert (idp->delete_op_head, idp->delete_op_tail, adh);
1563   adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1564                                                &adh->identity,
1565                                                adh->label,
1566                                                0,
1567                                                NULL,
1568                                                &attr_delete_cont,
1569                                                adh);
1570 }
1571
1572
1573 /**
1574    * Attestation deleted callback
1575    *
1576    * @param cls our handle
1577    * @param success success status
1578    * @param emsg error message (NULL if success=GNUNET_OK)
1579    */
1580 static void
1581 attest_delete_cont (void *cls, int32_t success, const char *emsg)
1582 {
1583   struct AttributeDeleteHandle *adh = cls;
1584
1585   adh->ns_qe = NULL;
1586   if (GNUNET_SYSERR == success)
1587   {
1588     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1589                 "Error deleting attestation %s\n",
1590                 adh->label);
1591     send_delete_response (adh, GNUNET_SYSERR);
1592     cleanup_adh (adh);
1593     return;
1594   }
1595   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating tickets...\n");
1596   GNUNET_SCHEDULER_add_now (&start_ticket_update, adh);
1597 }
1598
1599
1600 /**
1601  * Check attestation delete message format
1602  *
1603  * @cls unused
1604  * @dam message to check
1605  */
1606 static int
1607 check_attestation_delete_message (void *cls,
1608                                   const struct AttributeDeleteMessage *dam)
1609 {
1610   uint16_t size;
1611
1612   size = ntohs (dam->header.size);
1613   if (size <= sizeof(struct AttributeDeleteMessage))
1614   {
1615     GNUNET_break (0);
1616     return GNUNET_SYSERR;
1617   }
1618   return GNUNET_OK;
1619 }
1620
1621
1622 /**
1623  * Handle attestation deletion
1624  *
1625  * @param cls our client
1626  * @param dam deletion message
1627  */
1628 static void
1629 handle_attestation_delete_message (void *cls,
1630                                    const struct AttributeDeleteMessage *dam)
1631 {
1632   struct AttributeDeleteHandle *adh;
1633   struct IdpClient *idp = cls;
1634   size_t data_len;
1635
1636   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTESTATION_DELETE message\n");
1637
1638   data_len = ntohs (dam->attr_len);
1639
1640   adh = GNUNET_new (struct AttributeDeleteHandle);
1641   adh->attest = GNUNET_RECLAIM_attestation_deserialize ((char *) &dam[1],
1642                                                         data_len);
1643   adh->claim = NULL;
1644
1645   adh->r_id = ntohl (dam->id);
1646   adh->identity = dam->identity;
1647   adh->label
1648     = GNUNET_STRINGS_data_to_string_alloc (&adh->attest->id,
1649                                            sizeof(adh->attest->id));
1650   GNUNET_SERVICE_client_continue (idp->client);
1651   adh->client = idp;
1652   GNUNET_CONTAINER_DLL_insert (idp->delete_op_head, idp->delete_op_tail, adh);
1653   adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1654                                                &adh->identity,
1655                                                adh->label,
1656                                                0,
1657                                                NULL,
1658                                                &attest_delete_cont,
1659                                                adh);
1660 }
1661
1662
1663 /*************************************************
1664 * Attrubute iteration
1665 *************************************************/
1666
1667
1668 /**
1669  * Done iterating over attributes
1670  *
1671  * @param cls our iterator handle
1672  */
1673 static void
1674 attr_iter_finished (void *cls)
1675 {
1676   struct Iterator *ai = cls;
1677   struct GNUNET_MQ_Envelope *env;
1678   struct AttributeResultMessage *arm;
1679
1680   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending ATTRIBUTE_RESULT message\n");
1681   env = GNUNET_MQ_msg (arm, GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
1682   arm->id = htonl (ai->request_id);
1683   arm->attr_len = htons (0);
1684   GNUNET_MQ_send (ai->client->mq, env);
1685   GNUNET_CONTAINER_DLL_remove (ai->client->attr_iter_head,
1686                                ai->client->attr_iter_tail,
1687                                ai);
1688   GNUNET_free (ai);
1689 }
1690
1691
1692 /**
1693  * Error iterating over attributes. Abort.
1694  *
1695  * @param cls our attribute iteration handle
1696  */
1697 static void
1698 attr_iter_error (void *cls)
1699 {
1700   struct Iterator *ai = cls;
1701
1702   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to iterate over attributes\n");
1703   attr_iter_finished (ai);
1704 }
1705
1706
1707 /**
1708  * Got record. Return if it is an attribute or attestation.
1709  *
1710  * @param cls our attribute iterator
1711  * @param zone zone we are iterating
1712  * @param label label of the records
1713  * @param rd_count record count
1714  * @param rd records
1715  */
1716 static void
1717 attr_iter_cb (void *cls,
1718               const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1719               const char *label,
1720               unsigned int rd_count,
1721               const struct GNUNET_GNSRECORD_Data *rd)
1722 {
1723   struct Iterator *ai = cls;
1724   struct GNUNET_MQ_Envelope *env;
1725   char *data_tmp;
1726
1727   if ((rd_count != 1) ||
1728       (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE != rd->record_type))
1729   {
1730     GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1731     return;
1732   }
1733   struct AttributeResultMessage *arm;
1734   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found attribute under: %s\n",
1735               label);
1736   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1737               "Sending ATTRIBUTE_RESULT message\n");
1738   env = GNUNET_MQ_msg_extra (arm,
1739                              rd->data_size,
1740                              GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
1741   arm->id = htonl (ai->request_id);
1742   arm->attr_len = htons (rd->data_size);
1743   GNUNET_CRYPTO_ecdsa_key_get_public (zone, &arm->identity);
1744   data_tmp = (char *) &arm[1];
1745   GNUNET_memcpy (data_tmp, rd->data, rd->data_size);
1746   GNUNET_MQ_send (ai->client->mq, env);
1747 }
1748
1749
1750 /**
1751  * Iterate over zone to get attributes
1752  *
1753  * @param cls our client
1754  * @param ais_msg the iteration message to start
1755  */
1756 static void
1757 handle_iteration_start (void *cls,
1758                         const struct AttributeIterationStartMessage *ais_msg)
1759 {
1760   struct IdpClient *idp = cls;
1761   struct Iterator *ai;
1762
1763   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1764               "Received ATTRIBUTE_ITERATION_START message\n");
1765   ai = GNUNET_new (struct Iterator);
1766   ai->request_id = ntohl (ais_msg->id);
1767   ai->client = idp;
1768   ai->identity = ais_msg->identity;
1769
1770   GNUNET_CONTAINER_DLL_insert (idp->attr_iter_head, idp->attr_iter_tail, ai);
1771   ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh,
1772                                                      &ai->identity,
1773                                                      &attr_iter_error,
1774                                                      ai,
1775                                                      &attr_iter_cb,
1776                                                      ai,
1777                                                      &attr_iter_finished,
1778                                                      ai);
1779   GNUNET_SERVICE_client_continue (idp->client);
1780 }
1781
1782
1783 /**
1784  * Handle iteration stop message from client
1785  *
1786  * @param cls the client
1787  * @param ais_msg the stop message
1788  */
1789 static void
1790 handle_iteration_stop (void *cls,
1791                        const struct AttributeIterationStopMessage *ais_msg)
1792 {
1793   struct IdpClient *idp = cls;
1794   struct Iterator *ai;
1795   uint32_t rid;
1796
1797   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1798               "Received `%s' message\n",
1799               "ATTRIBUTE_ITERATION_STOP");
1800   rid = ntohl (ais_msg->id);
1801   for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
1802     if (ai->request_id == rid)
1803       break;
1804   if (NULL == ai)
1805   {
1806     GNUNET_break (0);
1807     GNUNET_SERVICE_client_drop (idp->client);
1808     return;
1809   }
1810   GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, idp->attr_iter_tail, ai);
1811   GNUNET_free (ai);
1812   GNUNET_SERVICE_client_continue (idp->client);
1813 }
1814
1815
1816 /**
1817  * Client requests next attribute from iterator
1818  *
1819  * @param cls the client
1820  * @param ais_msg the message
1821  */
1822 static void
1823 handle_iteration_next (void *cls,
1824                        const struct AttributeIterationNextMessage *ais_msg)
1825 {
1826   struct IdpClient *idp = cls;
1827   struct Iterator *ai;
1828   uint32_t rid;
1829
1830   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1831               "Received ATTRIBUTE_ITERATION_NEXT message\n");
1832   rid = ntohl (ais_msg->id);
1833   for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
1834     if (ai->request_id == rid)
1835       break;
1836   if (NULL == ai)
1837   {
1838     GNUNET_break (0);
1839     GNUNET_SERVICE_client_drop (idp->client);
1840     return;
1841   }
1842   GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1843   GNUNET_SERVICE_client_continue (idp->client);
1844 }
1845
1846
1847 /*************************************************
1848 * Attestation iteration
1849 *************************************************/
1850
1851
1852 /**
1853  * Done iterating over attestations
1854  *
1855  * @param cls our iterator handle
1856  */
1857 static void
1858 attest_iter_finished (void *cls)
1859 {
1860   struct Iterator *ai = cls;
1861   struct GNUNET_MQ_Envelope *env;
1862   struct AttestationResultMessage *arm;
1863
1864   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending ATTESTATION_RESULT message\n");
1865   env = GNUNET_MQ_msg (arm, GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_RESULT);
1866   arm->id = htonl (ai->request_id);
1867   arm->attestation_len = htons (0);
1868   GNUNET_MQ_send (ai->client->mq, env);
1869   GNUNET_CONTAINER_DLL_remove (ai->client->attest_iter_head,
1870                                ai->client->attest_iter_tail,
1871                                ai);
1872   GNUNET_free (ai);
1873 }
1874
1875
1876 /**
1877  * Error iterating over attestations. Abort.
1878  *
1879  * @param cls our attribute iteration handle
1880  */
1881 static void
1882 attest_iter_error (void *cls)
1883 {
1884   struct Iterator *ai = cls;
1885
1886   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to iterate over attestations\n");
1887   attest_iter_finished (ai);
1888 }
1889
1890
1891 /**
1892  * Got record. Return attestation.
1893  *
1894  * @param cls our attribute iterator
1895  * @param zone zone we are iterating
1896  * @param label label of the records
1897  * @param rd_count record count
1898  * @param rd records
1899  */
1900 static void
1901 attest_iter_cb (void *cls,
1902                 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1903                 const char *label,
1904                 unsigned int rd_count,
1905                 const struct GNUNET_GNSRECORD_Data *rd)
1906 {
1907   struct Iterator *ai = cls;
1908   struct GNUNET_MQ_Envelope *env;
1909   struct AttestationResultMessage *arm;
1910   char *data_tmp;
1911
1912   if ((rd_count != 1) ||
1913       (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION != rd->record_type))
1914   {
1915     GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1916     return;
1917   }
1918   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found attestation under: %s\n",
1919               label);
1920   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1921               "Sending ATTESTATION_RESULT message\n");
1922   env = GNUNET_MQ_msg_extra (arm,
1923                              rd->data_size,
1924                              GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_RESULT);
1925   arm->id = htonl (ai->request_id);
1926   arm->attestation_len = htons (rd->data_size);
1927   GNUNET_CRYPTO_ecdsa_key_get_public (zone, &arm->identity);
1928   data_tmp = (char *) &arm[1];
1929   GNUNET_memcpy (data_tmp, rd->data, rd->data_size);
1930
1931   GNUNET_MQ_send (ai->client->mq, env);
1932 }
1933
1934
1935 /**
1936  * Iterate over zone to get attributes
1937  *
1938  * @param cls our client
1939  * @param ais_msg the iteration message to start
1940  */
1941 static void
1942 handle_attestation_iteration_start (void *cls,
1943                                     const struct
1944                                     AttestationIterationStartMessage *ais_msg)
1945 {
1946   struct IdpClient *idp = cls;
1947   struct Iterator *ai;
1948
1949   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1950               "Received ATTESTATION_ITERATION_START message\n");
1951   ai = GNUNET_new (struct Iterator);
1952   ai->request_id = ntohl (ais_msg->id);
1953   ai->client = idp;
1954   ai->identity = ais_msg->identity;
1955
1956   GNUNET_CONTAINER_DLL_insert (idp->attest_iter_head, idp->attest_iter_tail,
1957                                ai);
1958   ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh,
1959                                                      &ai->identity,
1960                                                      &attest_iter_error,
1961                                                      ai,
1962                                                      &attest_iter_cb,
1963                                                      ai,
1964                                                      &attest_iter_finished,
1965                                                      ai);
1966   GNUNET_SERVICE_client_continue (idp->client);
1967 }
1968
1969
1970 /**
1971  * Handle iteration stop message from client
1972  *
1973  * @param cls the client
1974  * @param ais_msg the stop message
1975  */
1976 static void
1977 handle_attestation_iteration_stop (void *cls,
1978                                    const struct
1979                                    AttestationIterationStopMessage *ais_msg)
1980 {
1981   struct IdpClient *idp = cls;
1982   struct Iterator *ai;
1983   uint32_t rid;
1984
1985   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1986               "Received `%s' message\n",
1987               "ATTESTATION_ITERATION_STOP");
1988   rid = ntohl (ais_msg->id);
1989   for (ai = idp->attest_iter_head; NULL != ai; ai = ai->next)
1990     if (ai->request_id == rid)
1991       break;
1992   if (NULL == ai)
1993   {
1994     GNUNET_break (0);
1995     GNUNET_SERVICE_client_drop (idp->client);
1996     return;
1997   }
1998   GNUNET_CONTAINER_DLL_remove (idp->attest_iter_head, idp->attest_iter_tail,
1999                                ai);
2000   GNUNET_free (ai);
2001   GNUNET_SERVICE_client_continue (idp->client);
2002 }
2003
2004
2005 /**
2006  * Client requests next attestation from iterator
2007  *
2008  * @param cls the client
2009  * @param ais_msg the message
2010  */
2011 static void
2012 handle_attestation_iteration_next (void *cls,
2013                                    const struct
2014                                    AttestationIterationNextMessage *ais_msg)
2015 {
2016   struct IdpClient *idp = cls;
2017   struct Iterator *ai;
2018   uint32_t rid;
2019
2020   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2021               "Received ATTESTATION_ITERATION_NEXT message\n");
2022   rid = ntohl (ais_msg->id);
2023   for (ai = idp->attest_iter_head; NULL != ai; ai = ai->next)
2024     if (ai->request_id == rid)
2025       break;
2026   if (NULL == ai)
2027   {
2028     GNUNET_break (0);
2029     GNUNET_SERVICE_client_drop (idp->client);
2030     return;
2031   }
2032   GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
2033   GNUNET_SERVICE_client_continue (idp->client);
2034 }
2035
2036
2037 /******************************************************
2038 * Ticket iteration
2039 ******************************************************/
2040
2041 /**
2042  * Got a ticket. Return to client
2043  *
2044  * @param cls our ticket iterator
2045  * @param ticket the ticket
2046  */
2047 static void
2048 ticket_iter_cb (void *cls, struct GNUNET_RECLAIM_Ticket *ticket)
2049 {
2050   struct TicketIteration *ti = cls;
2051   struct GNUNET_MQ_Envelope *env;
2052   struct TicketResultMessage *trm;
2053
2054   env = GNUNET_MQ_msg (trm, GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
2055   if (NULL == ticket)
2056   {
2057     /* send empty response to indicate end of list */
2058     GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head,
2059                                  ti->client->ticket_iter_tail,
2060                                  ti);
2061   }
2062   else
2063   {
2064     trm->ticket = *ticket;
2065   }
2066   trm->id = htonl (ti->r_id);
2067   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending TICKET_RESULT message\n");
2068   GNUNET_MQ_send (ti->client->mq, env);
2069   if (NULL == ticket)
2070     GNUNET_free (ti);
2071 }
2072
2073
2074 /**
2075  * Client requests a ticket iteration
2076  *
2077  * @param cls the client
2078  * @param tis_msg the iteration request message
2079  */
2080 static void
2081 handle_ticket_iteration_start (
2082   void *cls,
2083   const struct TicketIterationStartMessage *tis_msg)
2084 {
2085   struct IdpClient *client = cls;
2086   struct TicketIteration *ti;
2087
2088   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2089               "Received TICKET_ITERATION_START message\n");
2090   ti = GNUNET_new (struct TicketIteration);
2091   ti->r_id = ntohl (tis_msg->id);
2092   ti->client = client;
2093
2094   GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
2095                                client->ticket_iter_tail,
2096                                ti);
2097   ti->iter
2098     = RECLAIM_TICKETS_iteration_start (&tis_msg->identity, &ticket_iter_cb, ti);
2099   GNUNET_SERVICE_client_continue (client->client);
2100 }
2101
2102
2103 /**
2104  * Client has had enough tickets
2105  *
2106  * @param cls the client
2107  * @param tis_msg the stop message
2108  */
2109 static void
2110 handle_ticket_iteration_stop (void *cls,
2111                               const struct TicketIterationStopMessage *tis_msg)
2112 {
2113   struct IdpClient *client = cls;
2114   struct TicketIteration *ti;
2115   uint32_t rid;
2116
2117   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2118               "Received `%s' message\n",
2119               "TICKET_ITERATION_STOP");
2120   rid = ntohl (tis_msg->id);
2121   for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2122     if (ti->r_id == rid)
2123       break;
2124   if (NULL == ti)
2125   {
2126     GNUNET_break (0);
2127     GNUNET_SERVICE_client_drop (client->client);
2128     return;
2129   }
2130   RECLAIM_TICKETS_iteration_stop (ti->iter);
2131   GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
2132                                client->ticket_iter_tail,
2133                                ti);
2134   GNUNET_free (ti);
2135   GNUNET_SERVICE_client_continue (client->client);
2136 }
2137
2138
2139 /**
2140  * Client requests next result.
2141  *
2142  * @param cls the client
2143  * @param tis_msg the message
2144  */
2145 static void
2146 handle_ticket_iteration_next (void *cls,
2147                               const struct TicketIterationNextMessage *tis_msg)
2148 {
2149   struct IdpClient *client = cls;
2150   struct TicketIteration *ti;
2151   uint32_t rid;
2152
2153   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2154               "Received TICKET_ITERATION_NEXT message\n");
2155   rid = ntohl (tis_msg->id);
2156   for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2157     if (ti->r_id == rid)
2158       break;
2159   if (NULL == ti)
2160   {
2161     GNUNET_break (0);
2162     GNUNET_SERVICE_client_drop (client->client);
2163     return;
2164   }
2165   RECLAIM_TICKETS_iteration_next (ti->iter);
2166   GNUNET_SERVICE_client_continue (client->client);
2167 }
2168
2169
2170 /**
2171  * Main function that will be run
2172  *
2173  * @param cls closure
2174  * @param c the configuration used
2175  * @param server the service handle
2176  */
2177 static void
2178 run (void *cls,
2179      const struct GNUNET_CONFIGURATION_Handle *c,
2180      struct GNUNET_SERVICE_Handle *server)
2181 {
2182   cfg = c;
2183
2184   if (GNUNET_OK != RECLAIM_TICKETS_init (cfg))
2185   {
2186     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2187                 "Unable to initialize TICKETS subsystem.\n");
2188     GNUNET_SCHEDULER_shutdown ();
2189     return;
2190   }
2191   // Connect to identity and namestore services
2192   nsh = GNUNET_NAMESTORE_connect (cfg);
2193   if (NULL == nsh)
2194   {
2195     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
2196                          "error connecting to namestore");
2197   }
2198
2199   GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
2200 }
2201
2202
2203 /**
2204  * Called whenever a client is disconnected.
2205  *
2206  * @param cls closure
2207  * @param client identification of the client
2208  * @param app_ctx @a client
2209  */
2210 static void
2211 client_disconnect_cb (void *cls,
2212                       struct GNUNET_SERVICE_Client *client,
2213                       void *app_ctx)
2214 {
2215   struct IdpClient *idp = app_ctx;
2216
2217   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client);
2218   GNUNET_CONTAINER_DLL_remove (client_list_head,
2219                                client_list_tail,
2220                                idp);
2221   cleanup_client (idp);
2222 }
2223
2224
2225 /**
2226  * Add a client to our list of active clients.
2227  *
2228  * @param cls NULL
2229  * @param client client to add
2230  * @param mq message queue for @a client
2231  * @return internal namestore client structure for this client
2232  */
2233 static void *
2234 client_connect_cb (void *cls,
2235                    struct GNUNET_SERVICE_Client *client,
2236                    struct GNUNET_MQ_Handle *mq)
2237 {
2238   struct IdpClient *idp;
2239
2240   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
2241   idp = GNUNET_new (struct IdpClient);
2242   idp->client = client;
2243   idp->mq = mq;
2244   GNUNET_CONTAINER_DLL_insert (client_list_head,
2245                                client_list_tail,
2246                                idp);
2247   return idp;
2248 }
2249
2250
2251 /**
2252  * Define "main" method using service macro.
2253  */
2254 GNUNET_SERVICE_MAIN (
2255   "reclaim",
2256   GNUNET_SERVICE_OPTION_NONE,
2257   &run,
2258   &client_connect_cb,
2259   &client_disconnect_cb,
2260   NULL,
2261   GNUNET_MQ_hd_var_size (attribute_store_message,
2262                          GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE,
2263                          struct AttributeStoreMessage,
2264                          NULL),
2265   GNUNET_MQ_hd_var_size (attestation_store_message,
2266                          GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_STORE,
2267                          struct AttributeStoreMessage,
2268                          NULL),
2269   GNUNET_MQ_hd_var_size (attribute_delete_message,
2270                          GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_DELETE,
2271                          struct AttributeDeleteMessage,
2272                          NULL),
2273   GNUNET_MQ_hd_var_size (attestation_delete_message,
2274                          GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_DELETE,
2275                          struct AttributeDeleteMessage,
2276                          NULL),
2277   GNUNET_MQ_hd_fixed_size (iteration_start,
2278                            GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_START,
2279                            struct AttributeIterationStartMessage,
2280                            NULL),
2281   GNUNET_MQ_hd_fixed_size (iteration_next,
2282                            GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT,
2283                            struct AttributeIterationNextMessage,
2284                            NULL),
2285   GNUNET_MQ_hd_fixed_size (iteration_stop,
2286                            GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP,
2287                            struct AttributeIterationStopMessage,
2288                            NULL),
2289   GNUNET_MQ_hd_fixed_size (attestation_iteration_start,
2290                            GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_START,
2291                            struct AttestationIterationStartMessage,
2292                            NULL),
2293   GNUNET_MQ_hd_fixed_size (attestation_iteration_next,
2294                            GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_NEXT,
2295                            struct AttestationIterationNextMessage,
2296                            NULL),
2297   GNUNET_MQ_hd_fixed_size (attestation_iteration_stop,
2298                            GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_STOP,
2299                            struct AttestationIterationStopMessage,
2300                            NULL),
2301
2302   GNUNET_MQ_hd_var_size (issue_ticket_message,
2303                          GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET,
2304                          struct IssueTicketMessage,
2305                          NULL),
2306   GNUNET_MQ_hd_var_size (consume_ticket_message,
2307                          GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET,
2308                          struct ConsumeTicketMessage,
2309                          NULL),
2310   GNUNET_MQ_hd_fixed_size (ticket_iteration_start,
2311                            GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_START,
2312                            struct TicketIterationStartMessage,
2313                            NULL),
2314   GNUNET_MQ_hd_fixed_size (ticket_iteration_next,
2315                            GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_NEXT,
2316                            struct TicketIterationNextMessage,
2317                            NULL),
2318   GNUNET_MQ_hd_fixed_size (ticket_iteration_stop,
2319                            GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_STOP,
2320                            struct TicketIterationStopMessage,
2321                            NULL),
2322   GNUNET_MQ_hd_var_size (revoke_ticket_message,
2323                          GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET,
2324                          struct RevokeTicketMessage,
2325                          NULL),
2326   GNUNET_MQ_handler_end ());
2327 /* end of gnunet-service-reclaim.c */