bugfixes
[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 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                    int32_t success,
846                    const char *emsg)
847 {
848   struct ConsumeTicketOperation *cop = cls;
849   struct ConsumeTicketResultMessage *crm;
850   struct GNUNET_MQ_Envelope *env;
851   char *data_tmp;
852   size_t attrs_len;
853
854   if (GNUNET_OK != success)
855   {
856     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error consuming ticket: %s\n", emsg);
857   }
858   attrs_len = GNUNET_RECLAIM_attribute_list_serialize_get_size (attrs);
859   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
860               "Sending CONSUME_TICKET_RESULT message\n");
861   env = GNUNET_MQ_msg_extra (crm,
862                              attrs_len,
863                              GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT);
864   crm->id = htonl (cop->r_id);
865   crm->attrs_len = htons (attrs_len);
866   crm->identity = *identity;
867   crm->result = htonl (success);
868   data_tmp = (char *) &crm[1];
869   GNUNET_RECLAIM_attribute_list_serialize (attrs, data_tmp);
870   GNUNET_MQ_send (cop->client->mq, env);
871   GNUNET_CONTAINER_DLL_remove (cop->client->consume_op_head,
872                                cop->client->consume_op_tail,
873                                cop);
874   GNUNET_free (cop);
875 }
876
877
878 /**
879  * Check a consume ticket message
880  *
881  * @param cls unused
882  * @param cm the message to handle
883  */
884 static int
885 check_consume_ticket_message (void *cls, const struct ConsumeTicketMessage *cm)
886 {
887   uint16_t size;
888
889   size = ntohs (cm->header.size);
890   if (size != sizeof(struct ConsumeTicketMessage))
891   {
892     GNUNET_break (0);
893     return GNUNET_SYSERR;
894   }
895   return GNUNET_OK;
896 }
897
898
899 /**
900  * Handle a consume ticket message
901  *
902  * @param cls our client handle
903  * @cm the message to handle
904  */
905 static void
906 handle_consume_ticket_message (void *cls, const struct ConsumeTicketMessage *cm)
907 {
908   struct ConsumeTicketOperation *cop;
909   struct IdpClient *idp = cls;
910
911   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received CONSUME_TICKET message\n");
912   cop = GNUNET_new (struct ConsumeTicketOperation);
913   cop->r_id = ntohl (cm->id);
914   cop->client = idp;
915   cop->ch
916     = RECLAIM_TICKETS_consume (&cm->identity, &cm->ticket, &consume_result_cb,
917                                cop);
918   GNUNET_CONTAINER_DLL_insert (idp->consume_op_head, idp->consume_op_tail, cop);
919   GNUNET_SERVICE_client_continue (idp->client);
920 }
921
922
923 /*****************************************
924 * Attribute store
925 *****************************************/
926
927
928 /**
929  * Attribute store result handler
930  *
931  * @param cls our attribute store handle
932  * @param success GNUNET_OK if successful
933  * @param emsg error message (NULL if success=GNUNET_OK)
934  */
935 static void
936 attr_store_cont (void *cls, int32_t success, const char *emsg)
937 {
938   struct AttributeStoreHandle *ash = cls;
939   struct GNUNET_MQ_Envelope *env;
940   struct SuccessResultMessage *acr_msg;
941
942   ash->ns_qe = NULL;
943   GNUNET_CONTAINER_DLL_remove (ash->client->store_op_head,
944                                ash->client->store_op_tail,
945                                ash);
946
947   if (GNUNET_SYSERR == success)
948   {
949     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
950                 "Failed to store attribute %s\n",
951                 emsg);
952     cleanup_as_handle (ash);
953     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
954     return;
955   }
956
957   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
958   env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
959   acr_msg->id = htonl (ash->r_id);
960   acr_msg->op_result = htonl (GNUNET_OK);
961   GNUNET_MQ_send (ash->client->mq, env);
962   cleanup_as_handle (ash);
963 }
964
965
966 /**
967  * Add a new attribute
968  *
969  * @param cls the AttributeStoreHandle
970  */
971 static void
972 attr_store_task (void *cls)
973 {
974   struct AttributeStoreHandle *ash = cls;
975   struct GNUNET_GNSRECORD_Data rd[1];
976   char *buf;
977   char *label;
978   size_t buf_size;
979
980   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Storing attribute\n");
981   buf_size = GNUNET_RECLAIM_attribute_serialize_get_size (ash->claim);
982   buf = GNUNET_malloc (buf_size);
983   // Give the ash a new id if unset
984   if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&ash->claim->id))
985     GNUNET_RECLAIM_id_generate (&ash->claim->id);
986   GNUNET_RECLAIM_attribute_serialize (ash->claim, buf);
987   label
988     = GNUNET_STRINGS_data_to_string_alloc (&ash->claim->id,
989                                            sizeof (ash->claim->id));
990   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting with label %s\n", label);
991
992   rd[0].data_size = buf_size;
993   rd[0].data = buf;
994   rd[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE;
995   rd[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
996   rd[0].expiration_time = ash->exp.rel_value_us;
997   ash->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
998                                                &ash->identity,
999                                                label,
1000                                                1,
1001                                                rd,
1002                                                &attr_store_cont,
1003                                                ash);
1004   GNUNET_free (buf);
1005   GNUNET_free (label);
1006 }
1007
1008
1009 /**
1010  * Check an attribute store message
1011  *
1012  * @param cls unused
1013  * @param sam the message to check
1014  */
1015 static int
1016 check_attribute_store_message (void *cls,
1017                                const struct AttributeStoreMessage *sam)
1018 {
1019   uint16_t size;
1020
1021   size = ntohs (sam->header.size);
1022   if (size <= sizeof(struct AttributeStoreMessage))
1023   {
1024     GNUNET_break (0);
1025     return GNUNET_SYSERR;
1026   }
1027   return GNUNET_OK;
1028 }
1029
1030
1031 /**
1032  * Handle an attribute store message
1033  *
1034  * @param cls our client
1035  * @param sam the message to handle
1036  */
1037 static void
1038 handle_attribute_store_message (void *cls,
1039                                 const struct AttributeStoreMessage *sam)
1040 {
1041   struct AttributeStoreHandle *ash;
1042   struct IdpClient *idp = cls;
1043   size_t data_len;
1044
1045   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTRIBUTE_STORE message\n");
1046
1047   data_len = ntohs (sam->attr_len);
1048
1049   ash = GNUNET_new (struct AttributeStoreHandle);
1050   ash->claim = GNUNET_RECLAIM_attribute_deserialize ((char *) &sam[1],
1051                                                      data_len);
1052
1053   ash->r_id = ntohl (sam->id);
1054   ash->identity = sam->identity;
1055   ash->exp.rel_value_us = GNUNET_ntohll (sam->exp);
1056   GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity, &ash->identity_pkey);
1057
1058   GNUNET_SERVICE_client_continue (idp->client);
1059   ash->client = idp;
1060   GNUNET_CONTAINER_DLL_insert (idp->store_op_head, idp->store_op_tail, ash);
1061   GNUNET_SCHEDULER_add_now (&attr_store_task, ash);
1062 }
1063
1064
1065 /**
1066  * Attestation store result handler
1067  *
1068  * @param cls our attribute store handle
1069  * @param success GNUNET_OK if successful
1070  * @param emsg error message (NULL if success=GNUNET_OK)
1071  */
1072 static void
1073 attest_store_cont (void *cls, int32_t success, const char *emsg)
1074 {
1075   struct AttributeStoreHandle *ash = cls;
1076   struct GNUNET_MQ_Envelope *env;
1077   struct SuccessResultMessage *acr_msg;
1078
1079   ash->ns_qe = NULL;
1080   GNUNET_CONTAINER_DLL_remove (ash->client->store_op_head,
1081                                ash->client->store_op_tail,
1082                                ash);
1083
1084   if (GNUNET_SYSERR == success)
1085   {
1086     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1087                 "Failed to store attestation %s\n",
1088                 emsg);
1089     cleanup_as_handle (ash);
1090     GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1091     return;
1092   }
1093
1094   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
1095   env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
1096   acr_msg->id = htonl (ash->r_id);
1097   acr_msg->op_result = htonl (GNUNET_OK);
1098   GNUNET_MQ_send (ash->client->mq, env);
1099   cleanup_as_handle (ash);
1100 }
1101
1102
1103 /**
1104  * Error looking up potential attestation. Abort.
1105  *
1106  * @param cls our attribute store handle
1107  */
1108 static void
1109 attest_error (void *cls)
1110 {
1111   struct AttributeStoreHandle *ash = cls;
1112   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1113               "Failed to check for existing Attestation\n");
1114   cleanup_as_handle (ash);
1115   GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
1116   return;
1117 }
1118
1119
1120 /**
1121 * Check for existing record before storing attestation
1122 *
1123 * @param cls our attribute store handle
1124 * @param zone zone we are iterating
1125 * @param label label of the records
1126 * @param rd_count record count
1127 * @param rd records
1128 */
1129 static void
1130 attest_add_cb (void *cls,
1131                const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1132                const char *label,
1133                unsigned int rd_count,
1134                const struct GNUNET_GNSRECORD_Data *rd)
1135 {
1136   struct AttributeStoreHandle *ash = cls;
1137   char *buf;
1138   size_t buf_size;
1139   buf_size = GNUNET_RECLAIM_attestation_serialize_get_size (ash->attest);
1140   buf = GNUNET_malloc (buf_size);
1141   GNUNET_RECLAIM_attestation_serialize (ash->attest, buf);
1142   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1143               "Storing new Attestation\n");
1144   struct GNUNET_GNSRECORD_Data rd_new[1];
1145   rd_new[0].data_size = buf_size;
1146   rd_new[0].data = buf;
1147   rd_new[0].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION;
1148   rd_new[0].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1149   rd_new[0].expiration_time = ash->exp.rel_value_us;
1150   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypting with label %s\n", label);
1151   ash->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1152                                                &ash->identity,
1153                                                label,
1154                                                1,
1155                                                rd_new,
1156                                                &attest_store_cont,
1157                                                ash);
1158   GNUNET_free (buf);
1159   return;
1160 }
1161
1162
1163 /**
1164  * Add a new attestation
1165  *
1166  * @param cls the AttributeStoreHandle
1167  */
1168 static void
1169 attest_store_task (void *cls)
1170 {
1171   struct AttributeStoreHandle *ash = cls;
1172   char *label;
1173
1174   // Give the ash a new id if unset
1175   if (GNUNET_YES == GNUNET_RECLAIM_id_is_zero (&ash->attest->id))
1176     GNUNET_RECLAIM_id_generate (&ash->attest->id);
1177   label = GNUNET_STRINGS_data_to_string_alloc (&ash->attest->id,
1178                                                sizeof (ash->attest->id));
1179   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1180               "Looking up existing data under label %s\n", label);
1181 // Test for the content of the existing ID
1182   ash->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh,
1183                                                 &ash->identity,
1184                                                 label,
1185                                                 &attest_error,
1186                                                 ash,
1187                                                 &attest_add_cb,
1188                                                 ash);
1189   GNUNET_free (label);
1190 }
1191
1192
1193 /**
1194  * Check an attestation store message
1195  *
1196  * @param cls unused
1197  * @param sam the message to check
1198  */
1199 static int
1200 check_attestation_store_message (void *cls,
1201                                  const struct AttributeStoreMessage *sam)
1202 {
1203   uint16_t size;
1204
1205   size = ntohs (sam->header.size);
1206   if (size <= sizeof(struct AttributeStoreMessage))
1207   {
1208     GNUNET_break (0);
1209     return GNUNET_SYSERR;
1210   }
1211   return GNUNET_OK;
1212 }
1213
1214
1215 /**
1216 * Handle an attestation store message
1217 *
1218 * @param cls our client
1219 * @param sam the message to handle
1220 */
1221 static void
1222 handle_attestation_store_message (void *cls,
1223                                   const struct AttributeStoreMessage *sam)
1224 {
1225   struct AttributeStoreHandle *ash;
1226   struct IdpClient *idp = cls;
1227   size_t data_len;
1228
1229   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTESTATION_STORE message\n");
1230
1231   data_len = ntohs (sam->attr_len);
1232
1233   ash = GNUNET_new (struct AttributeStoreHandle);
1234   ash->attest = GNUNET_RECLAIM_attestation_deserialize ((char *) &sam[1],
1235                                                         data_len);
1236
1237   ash->r_id = ntohl (sam->id);
1238   ash->identity = sam->identity;
1239   ash->exp.rel_value_us = GNUNET_ntohll (sam->exp);
1240   GNUNET_CRYPTO_ecdsa_key_get_public (&sam->identity, &ash->identity_pkey);
1241
1242   GNUNET_SERVICE_client_continue (idp->client);
1243   ash->client = idp;
1244   GNUNET_CONTAINER_DLL_insert (idp->store_op_head, idp->store_op_tail, ash);
1245   GNUNET_SCHEDULER_add_now (&attest_store_task, ash);
1246 }
1247
1248
1249 /**
1250  * Send a deletion success response
1251  *
1252  * @param adh our attribute deletion handle
1253  * @param success the success status
1254  */
1255 static void
1256 send_delete_response (struct AttributeDeleteHandle *adh, int32_t success)
1257 {
1258   struct GNUNET_MQ_Envelope *env;
1259   struct SuccessResultMessage *acr_msg;
1260
1261   GNUNET_CONTAINER_DLL_remove (adh->client->delete_op_head,
1262                                adh->client->delete_op_tail,
1263                                adh);
1264
1265   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUCCESS_RESPONSE message\n");
1266   env = GNUNET_MQ_msg (acr_msg, GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE);
1267   acr_msg->id = htonl (adh->r_id);
1268   acr_msg->op_result = htonl (success);
1269   GNUNET_MQ_send (adh->client->mq, env);
1270 }
1271
1272
1273 /**
1274  * Namestore iteration within attribute deletion.
1275  * We need to reissue tickets with the deleted attribute removed.
1276  *
1277  * @param cls our attribute deletion handle
1278  * @param zone the private key of the ticket issuer
1279  * @param label the label of the record
1280  * @param rd_count number of records
1281  * @param rd record data
1282  */
1283 static void
1284 ticket_iter (void *cls,
1285              const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1286              const char *label,
1287              unsigned int rd_count,
1288              const struct GNUNET_GNSRECORD_Data *rd)
1289 {
1290   struct AttributeDeleteHandle *adh = cls;
1291   struct TicketRecordsEntry *le;
1292   int has_changed = GNUNET_NO;
1293   for (int i = 0; i < rd_count; i++)
1294   {
1295     if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF != rd[i].record_type)
1296       continue;
1297     if (adh->claim != NULL)
1298       if (GNUNET_YES != GNUNET_RECLAIM_id_is_equal (rd[i].data,
1299                                                     &adh->claim->id))
1300         continue;
1301     if (adh->attest != NULL)
1302       if (GNUNET_YES != GNUNET_RECLAIM_id_is_equal (rd[i].data,
1303                                                     &adh->attest->id))
1304         continue;
1305     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1306                 "Attribute or Attestation to delete found (%s)\n",
1307                 adh->label);
1308     has_changed = GNUNET_YES;
1309     break;
1310   }
1311   if (GNUNET_YES == has_changed)
1312   {
1313     le = GNUNET_new (struct TicketRecordsEntry);
1314     le->data_size = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
1315     le->data = GNUNET_malloc (le->data_size);
1316     le->rd_count = rd_count;
1317     le->label = GNUNET_strdup (label);
1318     GNUNET_GNSRECORD_records_serialize (rd_count, rd, le->data_size, le->data);
1319     GNUNET_CONTAINER_DLL_insert (adh->tickets_to_update_head,
1320                                  adh->tickets_to_update_tail,
1321                                  le);
1322   }
1323   GNUNET_NAMESTORE_zone_iterator_next (adh->ns_it, 1);
1324 }
1325
1326
1327 /**
1328  * Recursion prototype for function
1329  * @param cls our deletion handle
1330  */
1331 static void
1332 update_tickets (void *cls);
1333
1334
1335 /**
1336  * Callback called when a ticket was updated
1337  *
1338  * @param cls our attribute deletion handle
1339  * @param success GNUNET_OK if successful
1340  * @param emsg error message (NULL if success=GNUNET_OK)
1341  */
1342 static void
1343 ticket_updated (void *cls, int32_t success, const char *emsg)
1344 {
1345   struct AttributeDeleteHandle *adh = cls;
1346
1347   adh->ns_qe = NULL;
1348   GNUNET_SCHEDULER_add_now (&update_tickets, adh);
1349 }
1350
1351
1352 /**
1353  * Update tickets: Remove shared attribute which has just been deleted.
1354  * This method is called recursively until all tickets are processed.
1355  * Eventually, the updated tickets are stored using ``update_tickets''.
1356  *
1357  * @param cls our attribute deletion handle
1358  */
1359 static void
1360 update_tickets (void *cls)
1361 {
1362   struct AttributeDeleteHandle *adh = cls;
1363   struct TicketRecordsEntry *le;
1364
1365   if (NULL == adh->tickets_to_update_head)
1366   {
1367     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1368                 "Finished updating tickets, success\n");
1369     send_delete_response (adh, GNUNET_OK);
1370     cleanup_adh (adh);
1371     return;
1372   }
1373   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1374               "Updating %s\n",
1375               adh->tickets_to_update_head->label);
1376   le = adh->tickets_to_update_head;
1377   GNUNET_CONTAINER_DLL_remove (adh->tickets_to_update_head,
1378                                adh->tickets_to_update_tail,
1379                                le);
1380   struct GNUNET_GNSRECORD_Data rd[le->rd_count];
1381   struct GNUNET_GNSRECORD_Data rd_new[le->rd_count - 1];
1382   if (GNUNET_OK != GNUNET_GNSRECORD_records_deserialize (le->data_size,
1383                                                          le->data,
1384                                                          le->rd_count,
1385                                                          rd))
1386   {
1387     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1388                 "Unable to deserialize record data!\n");
1389     send_delete_response (adh, GNUNET_SYSERR);
1390     cleanup_adh (adh);
1391     return;
1392   }
1393   int j = 0;
1394   for (int i = 0; i < le->rd_count; i++)
1395   {
1396     if (adh->claim != NULL)
1397       if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF == rd[i].record_type)
1398           && (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (rd[i].data,
1399                                                         &adh->claim->id)))
1400         continue;
1401     if (adh->attest != NULL)
1402       if ((GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF == rd[i].record_type)
1403           && (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (rd[i].data,
1404                                                         &adh->attest->id)))
1405         continue;
1406     rd_new[j] = rd[i];
1407     j++;
1408   }
1409   adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1410                                                &adh->identity,
1411                                                le->label,
1412                                                j,
1413                                                rd_new,
1414                                                &ticket_updated,
1415                                                adh);
1416   GNUNET_free (le->label);
1417   GNUNET_free (le->data);
1418   GNUNET_free (le);
1419 }
1420
1421
1422 /**
1423  * Done collecting affected tickets, start updating.
1424  *
1425  * @param cls our attribute deletion handle
1426  */
1427 static void
1428 ticket_iter_fin (void *cls)
1429 {
1430   struct AttributeDeleteHandle *adh = cls;
1431   adh->ns_it = NULL;
1432   GNUNET_SCHEDULER_add_now (&update_tickets, adh);
1433 }
1434
1435
1436 /**
1437  * Error collecting affected tickets. Abort.
1438  *
1439  * @param cls our attribute deletion handle
1440  */
1441 static void
1442 ticket_iter_err (void *cls)
1443 {
1444   struct AttributeDeleteHandle *adh = cls;
1445
1446   adh->ns_it = NULL;
1447   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1448               "Namestore error on delete %s\n",
1449               adh->label);
1450   send_delete_response (adh, GNUNET_SYSERR);
1451   cleanup_adh (adh);
1452 }
1453
1454
1455 /**
1456  * Start processing tickets which may still contain reference to deleted
1457  * attribute.
1458  *
1459  * @param cls attribute deletion handle
1460  */
1461 static void
1462 start_ticket_update (void *cls)
1463 {
1464   struct AttributeDeleteHandle *adh = cls;
1465
1466   adh->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh,
1467                                                       &adh->identity,
1468                                                       &ticket_iter_err,
1469                                                       adh,
1470                                                       &ticket_iter,
1471                                                       adh,
1472                                                       &ticket_iter_fin,
1473                                                       adh);
1474 }
1475
1476
1477 /**
1478  * Attribute deleted callback
1479  *
1480  * @param cls our handle
1481  * @param success success status
1482  * @param emsg error message (NULL if success=GNUNET_OK)
1483  */
1484 static void
1485 attr_delete_cont (void *cls, int32_t success, const char *emsg)
1486 {
1487   struct AttributeDeleteHandle *adh = cls;
1488
1489   adh->ns_qe = NULL;
1490   if (GNUNET_SYSERR == success)
1491   {
1492     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1493                 "Error deleting attribute %s\n",
1494                 adh->label);
1495     send_delete_response (adh, GNUNET_SYSERR);
1496     cleanup_adh (adh);
1497     return;
1498   }
1499   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating tickets...\n");
1500   GNUNET_SCHEDULER_add_now (&start_ticket_update, adh);
1501 }
1502
1503
1504 /**
1505  * Check attribute delete message format
1506  *
1507  * @cls unused
1508  * @dam message to check
1509  */
1510 static int
1511 check_attribute_delete_message (void *cls,
1512                                 const struct AttributeDeleteMessage *dam)
1513 {
1514   uint16_t size;
1515
1516   size = ntohs (dam->header.size);
1517   if (size <= sizeof(struct AttributeDeleteMessage))
1518   {
1519     GNUNET_break (0);
1520     return GNUNET_SYSERR;
1521   }
1522   return GNUNET_OK;
1523 }
1524
1525
1526 /**
1527  * Handle attribute deletion
1528  *
1529  * @param cls our client
1530  * @param dam deletion message
1531  */
1532 static void
1533 handle_attribute_delete_message (void *cls,
1534                                  const struct AttributeDeleteMessage *dam)
1535 {
1536   struct AttributeDeleteHandle *adh;
1537   struct IdpClient *idp = cls;
1538   size_t data_len;
1539
1540   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTRIBUTE_DELETE message\n");
1541
1542   data_len = ntohs (dam->attr_len);
1543
1544   adh = GNUNET_new (struct AttributeDeleteHandle);
1545   adh->claim = GNUNET_RECLAIM_attribute_deserialize ((char *) &dam[1],
1546                                                      data_len);
1547   adh->attest = NULL;
1548
1549   adh->r_id = ntohl (dam->id);
1550   adh->identity = dam->identity;
1551   adh->label
1552     = GNUNET_STRINGS_data_to_string_alloc (&adh->claim->id,
1553                                            sizeof(adh->claim->id));
1554   GNUNET_SERVICE_client_continue (idp->client);
1555   adh->client = idp;
1556   GNUNET_CONTAINER_DLL_insert (idp->delete_op_head, idp->delete_op_tail, adh);
1557   adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1558                                                &adh->identity,
1559                                                adh->label,
1560                                                0,
1561                                                NULL,
1562                                                &attr_delete_cont,
1563                                                adh);
1564 }
1565
1566
1567 /**
1568    * Attestation deleted callback
1569    *
1570    * @param cls our handle
1571    * @param success success status
1572    * @param emsg error message (NULL if success=GNUNET_OK)
1573    */
1574 static void
1575 attest_delete_cont (void *cls, int32_t success, const char *emsg)
1576 {
1577   struct AttributeDeleteHandle *adh = cls;
1578
1579   adh->ns_qe = NULL;
1580   if (GNUNET_SYSERR == success)
1581   {
1582     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1583                 "Error deleting attestation %s\n",
1584                 adh->label);
1585     send_delete_response (adh, GNUNET_SYSERR);
1586     cleanup_adh (adh);
1587     return;
1588   }
1589   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating tickets...\n");
1590   GNUNET_SCHEDULER_add_now (&start_ticket_update, adh);
1591 }
1592
1593
1594 /**
1595  * Check attestation delete message format
1596  *
1597  * @cls unused
1598  * @dam message to check
1599  */
1600 static int
1601 check_attestation_delete_message (void *cls,
1602                                   const struct AttributeDeleteMessage *dam)
1603 {
1604   uint16_t size;
1605
1606   size = ntohs (dam->header.size);
1607   if (size <= sizeof(struct AttributeDeleteMessage))
1608   {
1609     GNUNET_break (0);
1610     return GNUNET_SYSERR;
1611   }
1612   return GNUNET_OK;
1613 }
1614
1615
1616 /**
1617  * Handle attestation deletion
1618  *
1619  * @param cls our client
1620  * @param dam deletion message
1621  */
1622 static void
1623 handle_attestation_delete_message (void *cls,
1624                                    const struct AttributeDeleteMessage *dam)
1625 {
1626   struct AttributeDeleteHandle *adh;
1627   struct IdpClient *idp = cls;
1628   size_t data_len;
1629
1630   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ATTESTATION_DELETE message\n");
1631
1632   data_len = ntohs (dam->attr_len);
1633
1634   adh = GNUNET_new (struct AttributeDeleteHandle);
1635   adh->attest = GNUNET_RECLAIM_attestation_deserialize ((char *) &dam[1],
1636                                                         data_len);
1637   adh->claim = NULL;
1638
1639   adh->r_id = ntohl (dam->id);
1640   adh->identity = dam->identity;
1641   adh->label
1642     = GNUNET_STRINGS_data_to_string_alloc (&adh->attest->id,
1643                                            sizeof(adh->attest->id));
1644   GNUNET_SERVICE_client_continue (idp->client);
1645   adh->client = idp;
1646   GNUNET_CONTAINER_DLL_insert (idp->delete_op_head, idp->delete_op_tail, adh);
1647   adh->ns_qe = GNUNET_NAMESTORE_records_store (nsh,
1648                                                &adh->identity,
1649                                                adh->label,
1650                                                0,
1651                                                NULL,
1652                                                &attest_delete_cont,
1653                                                adh);
1654 }
1655
1656
1657 /*************************************************
1658 * Attrubute iteration
1659 *************************************************/
1660
1661
1662 /**
1663  * Done iterating over attributes
1664  *
1665  * @param cls our iterator handle
1666  */
1667 static void
1668 attr_iter_finished (void *cls)
1669 {
1670   struct Iterator *ai = cls;
1671   struct GNUNET_MQ_Envelope *env;
1672   struct AttributeResultMessage *arm;
1673
1674   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending ATTRIBUTE_RESULT message\n");
1675   env = GNUNET_MQ_msg (arm, GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
1676   arm->id = htonl (ai->request_id);
1677   arm->attr_len = htons (0);
1678   GNUNET_MQ_send (ai->client->mq, env);
1679   GNUNET_CONTAINER_DLL_remove (ai->client->attr_iter_head,
1680                                ai->client->attr_iter_tail,
1681                                ai);
1682   GNUNET_free (ai);
1683 }
1684
1685
1686 /**
1687  * Error iterating over attributes. Abort.
1688  *
1689  * @param cls our attribute iteration handle
1690  */
1691 static void
1692 attr_iter_error (void *cls)
1693 {
1694   struct Iterator *ai = cls;
1695
1696   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to iterate over attributes\n");
1697   attr_iter_finished (ai);
1698 }
1699
1700
1701 /**
1702  * Got record. Return if it is an attribute or attestation.
1703  *
1704  * @param cls our attribute iterator
1705  * @param zone zone we are iterating
1706  * @param label label of the records
1707  * @param rd_count record count
1708  * @param rd records
1709  */
1710 static void
1711 attr_iter_cb (void *cls,
1712               const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1713               const char *label,
1714               unsigned int rd_count,
1715               const struct GNUNET_GNSRECORD_Data *rd)
1716 {
1717   struct Iterator *ai = cls;
1718   struct GNUNET_MQ_Envelope *env;
1719   char *data_tmp;
1720
1721   if ((rd_count != 1) ||
1722       (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE != rd->record_type))
1723   {
1724     GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1725     return;
1726   }
1727   struct AttributeResultMessage *arm;
1728   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found attribute under: %s\n",
1729               label);
1730   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1731               "Sending ATTRIBUTE_RESULT message\n");
1732   env = GNUNET_MQ_msg_extra (arm,
1733                              rd->data_size,
1734                              GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT);
1735   arm->id = htonl (ai->request_id);
1736   arm->attr_len = htons (rd->data_size);
1737   GNUNET_CRYPTO_ecdsa_key_get_public (zone, &arm->identity);
1738   data_tmp = (char *) &arm[1];
1739   GNUNET_memcpy (data_tmp, rd->data, rd->data_size);
1740   GNUNET_MQ_send (ai->client->mq, env);
1741 }
1742
1743
1744 /**
1745  * Iterate over zone to get attributes
1746  *
1747  * @param cls our client
1748  * @param ais_msg the iteration message to start
1749  */
1750 static void
1751 handle_iteration_start (void *cls,
1752                         const struct AttributeIterationStartMessage *ais_msg)
1753 {
1754   struct IdpClient *idp = cls;
1755   struct Iterator *ai;
1756
1757   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1758               "Received ATTRIBUTE_ITERATION_START message\n");
1759   ai = GNUNET_new (struct Iterator);
1760   ai->request_id = ntohl (ais_msg->id);
1761   ai->client = idp;
1762   ai->identity = ais_msg->identity;
1763
1764   GNUNET_CONTAINER_DLL_insert (idp->attr_iter_head, idp->attr_iter_tail, ai);
1765   ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh,
1766                                                      &ai->identity,
1767                                                      &attr_iter_error,
1768                                                      ai,
1769                                                      &attr_iter_cb,
1770                                                      ai,
1771                                                      &attr_iter_finished,
1772                                                      ai);
1773   GNUNET_SERVICE_client_continue (idp->client);
1774 }
1775
1776
1777 /**
1778  * Handle iteration stop message from client
1779  *
1780  * @param cls the client
1781  * @param ais_msg the stop message
1782  */
1783 static void
1784 handle_iteration_stop (void *cls,
1785                        const struct AttributeIterationStopMessage *ais_msg)
1786 {
1787   struct IdpClient *idp = cls;
1788   struct Iterator *ai;
1789   uint32_t rid;
1790
1791   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1792               "Received `%s' message\n",
1793               "ATTRIBUTE_ITERATION_STOP");
1794   rid = ntohl (ais_msg->id);
1795   for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
1796     if (ai->request_id == rid)
1797       break;
1798   if (NULL == ai)
1799   {
1800     GNUNET_break (0);
1801     GNUNET_SERVICE_client_drop (idp->client);
1802     return;
1803   }
1804   GNUNET_CONTAINER_DLL_remove (idp->attr_iter_head, idp->attr_iter_tail, ai);
1805   GNUNET_free (ai);
1806   GNUNET_SERVICE_client_continue (idp->client);
1807 }
1808
1809
1810 /**
1811  * Client requests next attribute from iterator
1812  *
1813  * @param cls the client
1814  * @param ais_msg the message
1815  */
1816 static void
1817 handle_iteration_next (void *cls,
1818                        const struct AttributeIterationNextMessage *ais_msg)
1819 {
1820   struct IdpClient *idp = cls;
1821   struct Iterator *ai;
1822   uint32_t rid;
1823
1824   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1825               "Received ATTRIBUTE_ITERATION_NEXT message\n");
1826   rid = ntohl (ais_msg->id);
1827   for (ai = idp->attr_iter_head; NULL != ai; ai = ai->next)
1828     if (ai->request_id == rid)
1829       break;
1830   if (NULL == ai)
1831   {
1832     GNUNET_break (0);
1833     GNUNET_SERVICE_client_drop (idp->client);
1834     return;
1835   }
1836   GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1837   GNUNET_SERVICE_client_continue (idp->client);
1838 }
1839
1840
1841 /*************************************************
1842 * Attestation iteration
1843 *************************************************/
1844
1845
1846 /**
1847  * Done iterating over attestations
1848  *
1849  * @param cls our iterator handle
1850  */
1851 static void
1852 attest_iter_finished (void *cls)
1853 {
1854   struct Iterator *ai = cls;
1855   struct GNUNET_MQ_Envelope *env;
1856   struct AttestationResultMessage *arm;
1857
1858   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending ATTESTATION_RESULT message\n");
1859   env = GNUNET_MQ_msg (arm, GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_RESULT);
1860   arm->id = htonl (ai->request_id);
1861   arm->attestation_len = htons (0);
1862   arm->attributes_len = htons (0);
1863   GNUNET_MQ_send (ai->client->mq, env);
1864   GNUNET_CONTAINER_DLL_remove (ai->client->attest_iter_head,
1865                                ai->client->attest_iter_tail,
1866                                ai);
1867   GNUNET_free (ai);
1868 }
1869
1870
1871 /**
1872  * Error iterating over attestations. Abort.
1873  *
1874  * @param cls our attribute iteration handle
1875  */
1876 static void
1877 attest_iter_error (void *cls)
1878 {
1879   struct Iterator *ai = cls;
1880
1881   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to iterate over attestations\n");
1882   attest_iter_finished (ai);
1883 }
1884
1885
1886 /**
1887  * Got record. Return attestation.
1888  *
1889  * @param cls our attribute iterator
1890  * @param zone zone we are iterating
1891  * @param label label of the records
1892  * @param rd_count record count
1893  * @param rd records
1894  */
1895 static void
1896 attest_iter_cb (void *cls,
1897                 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
1898                 const char *label,
1899                 unsigned int rd_count,
1900                 const struct GNUNET_GNSRECORD_Data *rd)
1901 {
1902   struct Iterator *ai = cls;
1903   struct GNUNET_MQ_Envelope *env;
1904   struct AttestationResultMessage *arm;
1905   struct GNUNET_RECLAIM_AttributeList *attrs;
1906   struct GNUNET_RECLAIM_Attestation *att;
1907   char *data_tmp;
1908   size_t attrs_size;
1909
1910   if ((rd_count != 1) ||
1911       (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTESTATION != rd->record_type))
1912   {
1913     GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
1914     return;
1915   }
1916   att = GNUNET_RECLAIM_attestation_deserialize (rd->data,
1917                                                 rd->data_size);
1918   attrs = GNUNET_RECLAIM_attestation_get_attributes (att);
1919   attrs_size = GNUNET_RECLAIM_attribute_list_serialize_get_size (attrs);
1920   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found attestation under: %s\n",
1921               label);
1922   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1923               "Sending ATTESTATION_RESULT message\n");
1924   env = GNUNET_MQ_msg_extra (arm,
1925                              rd->data_size + attrs_size,
1926                              GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_RESULT);
1927   arm->id = htonl (ai->request_id);
1928   arm->attestation_len = htons (rd->data_size);
1929   arm->attributes_len = htons (attrs_size);
1930   GNUNET_CRYPTO_ecdsa_key_get_public (zone, &arm->identity);
1931   data_tmp = (char *) &arm[1];
1932   GNUNET_memcpy (data_tmp, rd->data, rd->data_size);
1933   data_tmp += rd->data_size;
1934   GNUNET_RECLAIM_attribute_list_serialize (attrs,
1935                                            data_tmp);
1936
1937   GNUNET_MQ_send (ai->client->mq, env);
1938 }
1939
1940
1941 /**
1942  * Iterate over zone to get attributes
1943  *
1944  * @param cls our client
1945  * @param ais_msg the iteration message to start
1946  */
1947 static void
1948 handle_attestation_iteration_start (void *cls,
1949                                     const struct
1950                                     AttestationIterationStartMessage *ais_msg)
1951 {
1952   struct IdpClient *idp = cls;
1953   struct Iterator *ai;
1954
1955   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1956               "Received ATTESTATION_ITERATION_START message\n");
1957   ai = GNUNET_new (struct Iterator);
1958   ai->request_id = ntohl (ais_msg->id);
1959   ai->client = idp;
1960   ai->identity = ais_msg->identity;
1961
1962   GNUNET_CONTAINER_DLL_insert (idp->attest_iter_head, idp->attest_iter_tail,
1963                                ai);
1964   ai->ns_it = GNUNET_NAMESTORE_zone_iteration_start (nsh,
1965                                                      &ai->identity,
1966                                                      &attest_iter_error,
1967                                                      ai,
1968                                                      &attest_iter_cb,
1969                                                      ai,
1970                                                      &attest_iter_finished,
1971                                                      ai);
1972   GNUNET_SERVICE_client_continue (idp->client);
1973 }
1974
1975
1976 /**
1977  * Handle iteration stop message from client
1978  *
1979  * @param cls the client
1980  * @param ais_msg the stop message
1981  */
1982 static void
1983 handle_attestation_iteration_stop (void *cls,
1984                                    const struct
1985                                    AttestationIterationStopMessage *ais_msg)
1986 {
1987   struct IdpClient *idp = cls;
1988   struct Iterator *ai;
1989   uint32_t rid;
1990
1991   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1992               "Received `%s' message\n",
1993               "ATTESTATION_ITERATION_STOP");
1994   rid = ntohl (ais_msg->id);
1995   for (ai = idp->attest_iter_head; NULL != ai; ai = ai->next)
1996     if (ai->request_id == rid)
1997       break;
1998   if (NULL == ai)
1999   {
2000     GNUNET_break (0);
2001     GNUNET_SERVICE_client_drop (idp->client);
2002     return;
2003   }
2004   GNUNET_CONTAINER_DLL_remove (idp->attest_iter_head, idp->attest_iter_tail,
2005                                ai);
2006   GNUNET_free (ai);
2007   GNUNET_SERVICE_client_continue (idp->client);
2008 }
2009
2010
2011 /**
2012  * Client requests next attestation from iterator
2013  *
2014  * @param cls the client
2015  * @param ais_msg the message
2016  */
2017 static void
2018 handle_attestation_iteration_next (void *cls,
2019                                    const struct
2020                                    AttestationIterationNextMessage *ais_msg)
2021 {
2022   struct IdpClient *idp = cls;
2023   struct Iterator *ai;
2024   uint32_t rid;
2025
2026   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2027               "Received ATTESTATION_ITERATION_NEXT message\n");
2028   rid = ntohl (ais_msg->id);
2029   for (ai = idp->attest_iter_head; NULL != ai; ai = ai->next)
2030     if (ai->request_id == rid)
2031       break;
2032   if (NULL == ai)
2033   {
2034     GNUNET_break (0);
2035     GNUNET_SERVICE_client_drop (idp->client);
2036     return;
2037   }
2038   GNUNET_NAMESTORE_zone_iterator_next (ai->ns_it, 1);
2039   GNUNET_SERVICE_client_continue (idp->client);
2040 }
2041
2042
2043 /******************************************************
2044 * Ticket iteration
2045 ******************************************************/
2046
2047 /**
2048  * Got a ticket. Return to client
2049  *
2050  * @param cls our ticket iterator
2051  * @param ticket the ticket
2052  */
2053 static void
2054 ticket_iter_cb (void *cls, struct GNUNET_RECLAIM_Ticket *ticket)
2055 {
2056   struct TicketIteration *ti = cls;
2057   struct GNUNET_MQ_Envelope *env;
2058   struct TicketResultMessage *trm;
2059
2060   env = GNUNET_MQ_msg (trm, GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT);
2061   if (NULL == ticket)
2062   {
2063     /* send empty response to indicate end of list */
2064     GNUNET_CONTAINER_DLL_remove (ti->client->ticket_iter_head,
2065                                  ti->client->ticket_iter_tail,
2066                                  ti);
2067   }
2068   else
2069   {
2070     trm->ticket = *ticket;
2071   }
2072   trm->id = htonl (ti->r_id);
2073   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending TICKET_RESULT message\n");
2074   GNUNET_MQ_send (ti->client->mq, env);
2075   if (NULL == ticket)
2076     GNUNET_free (ti);
2077 }
2078
2079
2080 /**
2081  * Client requests a ticket iteration
2082  *
2083  * @param cls the client
2084  * @param tis_msg the iteration request message
2085  */
2086 static void
2087 handle_ticket_iteration_start (
2088   void *cls,
2089   const struct TicketIterationStartMessage *tis_msg)
2090 {
2091   struct IdpClient *client = cls;
2092   struct TicketIteration *ti;
2093
2094   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2095               "Received TICKET_ITERATION_START message\n");
2096   ti = GNUNET_new (struct TicketIteration);
2097   ti->r_id = ntohl (tis_msg->id);
2098   ti->client = client;
2099
2100   GNUNET_CONTAINER_DLL_insert (client->ticket_iter_head,
2101                                client->ticket_iter_tail,
2102                                ti);
2103   ti->iter
2104     = RECLAIM_TICKETS_iteration_start (&tis_msg->identity, &ticket_iter_cb, ti);
2105   GNUNET_SERVICE_client_continue (client->client);
2106 }
2107
2108
2109 /**
2110  * Client has had enough tickets
2111  *
2112  * @param cls the client
2113  * @param tis_msg the stop message
2114  */
2115 static void
2116 handle_ticket_iteration_stop (void *cls,
2117                               const struct TicketIterationStopMessage *tis_msg)
2118 {
2119   struct IdpClient *client = cls;
2120   struct TicketIteration *ti;
2121   uint32_t rid;
2122
2123   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2124               "Received `%s' message\n",
2125               "TICKET_ITERATION_STOP");
2126   rid = ntohl (tis_msg->id);
2127   for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2128     if (ti->r_id == rid)
2129       break;
2130   if (NULL == ti)
2131   {
2132     GNUNET_break (0);
2133     GNUNET_SERVICE_client_drop (client->client);
2134     return;
2135   }
2136   RECLAIM_TICKETS_iteration_stop (ti->iter);
2137   GNUNET_CONTAINER_DLL_remove (client->ticket_iter_head,
2138                                client->ticket_iter_tail,
2139                                ti);
2140   GNUNET_free (ti);
2141   GNUNET_SERVICE_client_continue (client->client);
2142 }
2143
2144
2145 /**
2146  * Client requests next result.
2147  *
2148  * @param cls the client
2149  * @param tis_msg the message
2150  */
2151 static void
2152 handle_ticket_iteration_next (void *cls,
2153                               const struct TicketIterationNextMessage *tis_msg)
2154 {
2155   struct IdpClient *client = cls;
2156   struct TicketIteration *ti;
2157   uint32_t rid;
2158
2159   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2160               "Received TICKET_ITERATION_NEXT message\n");
2161   rid = ntohl (tis_msg->id);
2162   for (ti = client->ticket_iter_head; NULL != ti; ti = ti->next)
2163     if (ti->r_id == rid)
2164       break;
2165   if (NULL == ti)
2166   {
2167     GNUNET_break (0);
2168     GNUNET_SERVICE_client_drop (client->client);
2169     return;
2170   }
2171   RECLAIM_TICKETS_iteration_next (ti->iter);
2172   GNUNET_SERVICE_client_continue (client->client);
2173 }
2174
2175
2176 /**
2177  * Main function that will be run
2178  *
2179  * @param cls closure
2180  * @param c the configuration used
2181  * @param server the service handle
2182  */
2183 static void
2184 run (void *cls,
2185      const struct GNUNET_CONFIGURATION_Handle *c,
2186      struct GNUNET_SERVICE_Handle *server)
2187 {
2188   cfg = c;
2189
2190   if (GNUNET_OK != RECLAIM_TICKETS_init (cfg))
2191   {
2192     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2193                 "Unable to initialize TICKETS subsystem.\n");
2194     GNUNET_SCHEDULER_shutdown ();
2195     return;
2196   }
2197   // Connect to identity and namestore services
2198   nsh = GNUNET_NAMESTORE_connect (cfg);
2199   if (NULL == nsh)
2200   {
2201     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
2202                          "error connecting to namestore");
2203   }
2204
2205   GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
2206 }
2207
2208
2209 /**
2210  * Called whenever a client is disconnected.
2211  *
2212  * @param cls closure
2213  * @param client identification of the client
2214  * @param app_ctx @a client
2215  */
2216 static void
2217 client_disconnect_cb (void *cls,
2218                       struct GNUNET_SERVICE_Client *client,
2219                       void *app_ctx)
2220 {
2221   struct IdpClient *idp = app_ctx;
2222
2223   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client);
2224   GNUNET_CONTAINER_DLL_remove (client_list_head,
2225                                client_list_tail,
2226                                idp);
2227   cleanup_client (idp);
2228 }
2229
2230
2231 /**
2232  * Add a client to our list of active clients.
2233  *
2234  * @param cls NULL
2235  * @param client client to add
2236  * @param mq message queue for @a client
2237  * @return internal namestore client structure for this client
2238  */
2239 static void *
2240 client_connect_cb (void *cls,
2241                    struct GNUNET_SERVICE_Client *client,
2242                    struct GNUNET_MQ_Handle *mq)
2243 {
2244   struct IdpClient *idp;
2245
2246   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
2247   idp = GNUNET_new (struct IdpClient);
2248   idp->client = client;
2249   idp->mq = mq;
2250   GNUNET_CONTAINER_DLL_insert (client_list_head,
2251                                client_list_tail,
2252                                idp);
2253   return idp;
2254 }
2255
2256
2257 /**
2258  * Define "main" method using service macro.
2259  */
2260 GNUNET_SERVICE_MAIN (
2261   "reclaim",
2262   GNUNET_SERVICE_OPTION_NONE,
2263   &run,
2264   &client_connect_cb,
2265   &client_disconnect_cb,
2266   NULL,
2267   GNUNET_MQ_hd_var_size (attribute_store_message,
2268                          GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE,
2269                          struct AttributeStoreMessage,
2270                          NULL),
2271   GNUNET_MQ_hd_var_size (attestation_store_message,
2272                          GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_STORE,
2273                          struct AttributeStoreMessage,
2274                          NULL),
2275   GNUNET_MQ_hd_var_size (attribute_delete_message,
2276                          GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_DELETE,
2277                          struct AttributeDeleteMessage,
2278                          NULL),
2279   GNUNET_MQ_hd_var_size (attestation_delete_message,
2280                          GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_DELETE,
2281                          struct AttributeDeleteMessage,
2282                          NULL),
2283   GNUNET_MQ_hd_fixed_size (iteration_start,
2284                            GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_START,
2285                            struct AttributeIterationStartMessage,
2286                            NULL),
2287   GNUNET_MQ_hd_fixed_size (iteration_next,
2288                            GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT,
2289                            struct AttributeIterationNextMessage,
2290                            NULL),
2291   GNUNET_MQ_hd_fixed_size (iteration_stop,
2292                            GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP,
2293                            struct AttributeIterationStopMessage,
2294                            NULL),
2295   GNUNET_MQ_hd_fixed_size (attestation_iteration_start,
2296                            GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_START,
2297                            struct AttestationIterationStartMessage,
2298                            NULL),
2299   GNUNET_MQ_hd_fixed_size (attestation_iteration_next,
2300                            GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_NEXT,
2301                            struct AttestationIterationNextMessage,
2302                            NULL),
2303   GNUNET_MQ_hd_fixed_size (attestation_iteration_stop,
2304                            GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_STOP,
2305                            struct AttestationIterationStopMessage,
2306                            NULL),
2307
2308   GNUNET_MQ_hd_var_size (issue_ticket_message,
2309                          GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET,
2310                          struct IssueTicketMessage,
2311                          NULL),
2312   GNUNET_MQ_hd_var_size (consume_ticket_message,
2313                          GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET,
2314                          struct ConsumeTicketMessage,
2315                          NULL),
2316   GNUNET_MQ_hd_fixed_size (ticket_iteration_start,
2317                            GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_START,
2318                            struct TicketIterationStartMessage,
2319                            NULL),
2320   GNUNET_MQ_hd_fixed_size (ticket_iteration_next,
2321                            GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_NEXT,
2322                            struct TicketIterationNextMessage,
2323                            NULL),
2324   GNUNET_MQ_hd_fixed_size (ticket_iteration_stop,
2325                            GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_STOP,
2326                            struct TicketIterationStopMessage,
2327                            NULL),
2328   GNUNET_MQ_hd_var_size (revoke_ticket_message,
2329                          GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET,
2330                          struct RevokeTicketMessage,
2331                          NULL),
2332   GNUNET_MQ_handler_end ());
2333 /* end of gnunet-service-reclaim.c */