towards better API
[oweals/gnunet.git] / src / reclaim / reclaim_api.c
1 /*
2    This file is part of GNUnet.
3    Copyright (C) 2016 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 /**
22  * @file reclaim/reclaim_api.c
23  * @brief api to interact with the reclaim service
24  * @author Martin Schanzenbach
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_constants.h"
29 #include "gnunet_mq_lib.h"
30 #include "gnunet_protocols.h"
31 #include "gnunet_reclaim_attribute_lib.h"
32 #include "gnunet_reclaim_service.h"
33 #include "reclaim.h"
34
35 #define LOG(kind, ...) GNUNET_log_from (kind, "reclaim-api", __VA_ARGS__)
36
37
38 /**
39  * Handle for an operation with the service.
40  */
41 struct GNUNET_RECLAIM_Operation
42 {
43   /**
44    * Main handle.
45    */
46   struct GNUNET_RECLAIM_Handle *h;
47
48   /**
49    * We keep operations in a DLL.
50    */
51   struct GNUNET_RECLAIM_Operation *next;
52
53   /**
54    * We keep operations in a DLL.
55    */
56   struct GNUNET_RECLAIM_Operation *prev;
57
58   /**
59    * Message to send to the service.
60    * Allocated at the end of this struct.
61    */
62   const struct GNUNET_MessageHeader *msg;
63
64   /**
65    * Continuation to invoke after attribute store call
66    */
67   GNUNET_RECLAIM_ContinuationWithStatus as_cb;
68
69   /**
70    * Attribute result callback
71    */
72   GNUNET_RECLAIM_AttributeResult ar_cb;
73
74   /**
75    * Attribute result callback
76    */
77   GNUNET_RECLAIM_AttributeTicketResult atr_cb;
78
79   /**
80    * Attestation result callback
81    */
82   GNUNET_RECLAIM_AttestationResult at_cb;
83
84   /**
85    * Revocation result callback
86    */
87   GNUNET_RECLAIM_ContinuationWithStatus rvk_cb;
88
89   /**
90    * Ticket result callback
91    */
92   GNUNET_RECLAIM_TicketCallback tr_cb;
93
94   /**
95    * Envelope with the message for this queue entry.
96    */
97   struct GNUNET_MQ_Envelope *env;
98
99   /**
100    * request id
101    */
102   uint32_t r_id;
103
104   /**
105    * Closure for @e cont or @e cb.
106    */
107   void *cls;
108 };
109
110
111 /**
112  * Handle for a ticket iterator operation
113  */
114 struct GNUNET_RECLAIM_TicketIterator
115 {
116   /**
117    * Kept in a DLL.
118    */
119   struct GNUNET_RECLAIM_TicketIterator *next;
120
121   /**
122    * Kept in a DLL.
123    */
124   struct GNUNET_RECLAIM_TicketIterator *prev;
125
126   /**
127    * Main handle to access the idp.
128    */
129   struct GNUNET_RECLAIM_Handle *h;
130
131   /**
132    * Function to call on completion.
133    */
134   GNUNET_SCHEDULER_TaskCallback finish_cb;
135
136   /**
137    * Closure for @e finish_cb.
138    */
139   void *finish_cb_cls;
140
141   /**
142    * The continuation to call with the results
143    */
144   GNUNET_RECLAIM_TicketCallback tr_cb;
145
146   /**
147    * Closure for @e tr_cb.
148    */
149   void *cls;
150
151   /**
152    * Function to call on errors.
153    */
154   GNUNET_SCHEDULER_TaskCallback error_cb;
155
156   /**
157    * Closure for @e error_cb.
158    */
159   void *error_cb_cls;
160
161   /**
162    * Envelope of the message to send to the service, if not yet
163    * sent.
164    */
165   struct GNUNET_MQ_Envelope *env;
166
167   /**
168    * The operation id this zone iteration operation has
169    */
170   uint32_t r_id;
171 };
172
173
174 /**
175  * Handle for a attribute iterator operation
176  */
177 struct GNUNET_RECLAIM_AttributeIterator
178 {
179   /**
180    * Kept in a DLL.
181    */
182   struct GNUNET_RECLAIM_AttributeIterator *next;
183
184   /**
185    * Kept in a DLL.
186    */
187   struct GNUNET_RECLAIM_AttributeIterator *prev;
188
189   /**
190    * Main handle to access the service.
191    */
192   struct GNUNET_RECLAIM_Handle *h;
193
194   /**
195    * Function to call on completion.
196    */
197   GNUNET_SCHEDULER_TaskCallback finish_cb;
198
199   /**
200    * Closure for @e finish_cb.
201    */
202   void *finish_cb_cls;
203
204   /**
205    * The continuation to call with the results
206    */
207   GNUNET_RECLAIM_AttributeResult proc;
208
209   /**
210    * Closure for @e proc.
211    */
212   void *proc_cls;
213
214   /**
215    * Function to call on errors.
216    */
217   GNUNET_SCHEDULER_TaskCallback error_cb;
218
219   /**
220    * Closure for @e error_cb.
221    */
222   void *error_cb_cls;
223
224   /**
225    * Envelope of the message to send to the service, if not yet
226    * sent.
227    */
228   struct GNUNET_MQ_Envelope *env;
229
230   /**
231    * Private key of the zone.
232    */
233   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
234
235   /**
236    * The operation id this zone iteration operation has
237    */
238   uint32_t r_id;
239 };
240
241 /**
242  * Handle for a attestation iterator operation
243  */
244 struct GNUNET_RECLAIM_AttestationIterator
245 {
246   /**
247    * Kept in a DLL.
248    */
249   struct GNUNET_RECLAIM_AttestationIterator *next;
250
251   /**
252    * Kept in a DLL.
253    */
254   struct GNUNET_RECLAIM_AttestationIterator *prev;
255
256   /**
257    * Main handle to access the service.
258    */
259   struct GNUNET_RECLAIM_Handle *h;
260
261   /**
262    * Function to call on completion.
263    */
264   GNUNET_SCHEDULER_TaskCallback finish_cb;
265
266   /**
267    * Closure for @e finish_cb.
268    */
269   void *finish_cb_cls;
270
271   /**
272    * The continuation to call with the results
273    */
274   GNUNET_RECLAIM_AttestationResult proc;
275
276   /**
277    * Closure for @e proc.
278    */
279   void *proc_cls;
280
281   /**
282    * Function to call on errors.
283    */
284   GNUNET_SCHEDULER_TaskCallback error_cb;
285
286   /**
287    * Closure for @e error_cb.
288    */
289   void *error_cb_cls;
290
291   /**
292    * Envelope of the message to send to the service, if not yet
293    * sent.
294    */
295   struct GNUNET_MQ_Envelope *env;
296
297   /**
298    * Private key of the zone.
299    */
300   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
301
302   /**
303    * The operation id this zone iteration operation has
304    */
305   uint32_t r_id;
306 };
307
308
309 /**
310  * Handle to the service.
311  */
312 struct GNUNET_RECLAIM_Handle
313 {
314   /**
315    * Configuration to use.
316    */
317   const struct GNUNET_CONFIGURATION_Handle *cfg;
318
319   /**
320    * Socket (if available).
321    */
322   struct GNUNET_CLIENT_Connection *client;
323
324   /**
325    * Closure for 'cb'.
326    */
327   void *cb_cls;
328
329   /**
330    * Head of active operations.
331    */
332   struct GNUNET_RECLAIM_Operation *op_head;
333
334   /**
335    * Tail of active operations.
336    */
337   struct GNUNET_RECLAIM_Operation *op_tail;
338
339   /**
340    * Head of active iterations
341    */
342   struct GNUNET_RECLAIM_AttributeIterator *it_head;
343
344   /**
345    * Tail of active iterations
346    */
347   struct GNUNET_RECLAIM_AttributeIterator *it_tail;
348
349   /**
350    * Head of active iterations
351    */
352   struct GNUNET_RECLAIM_AttestationIterator *ait_head;
353
354   /**
355    * Tail of active iterations
356    */
357   struct GNUNET_RECLAIM_AttestationIterator *ait_tail;
358
359   /**
360    * Head of active iterations
361    */
362   struct GNUNET_RECLAIM_TicketIterator *ticket_it_head;
363
364   /**
365    * Tail of active iterations
366    */
367   struct GNUNET_RECLAIM_TicketIterator *ticket_it_tail;
368
369   /**
370    * Currently pending transmission request, or NULL for none.
371    */
372   struct GNUNET_CLIENT_TransmitHandle *th;
373
374   /**
375    * Task doing exponential back-off trying to reconnect.
376    */
377   struct GNUNET_SCHEDULER_Task *reconnect_task;
378
379   /**
380    * Time for next connect retry.
381    */
382   struct GNUNET_TIME_Relative reconnect_backoff;
383
384   /**
385    * Connection to service (if available).
386    */
387   struct GNUNET_MQ_Handle *mq;
388
389   /**
390    * Request Id generator.  Incremented by one for each request.
391    */
392   uint32_t r_id_gen;
393
394   /**
395    * Are we polling for incoming messages right now?
396    */
397   int in_receive;
398 };
399
400
401 /**
402  * Try again to connect to the service.
403  *
404  * @param h handle to the reclaim service.
405  */
406 static void
407 reconnect (struct GNUNET_RECLAIM_Handle *h);
408
409
410 /**
411  * Reconnect
412  *
413  * @param cls the handle
414  */
415 static void
416 reconnect_task (void *cls)
417 {
418   struct GNUNET_RECLAIM_Handle *handle = cls;
419
420   handle->reconnect_task = NULL;
421   reconnect (handle);
422 }
423
424
425 /**
426  * Disconnect from service and then reconnect.
427  *
428  * @param handle our service
429  */
430 static void
431 force_reconnect (struct GNUNET_RECLAIM_Handle *handle)
432 {
433   GNUNET_MQ_destroy (handle->mq);
434   handle->mq = NULL;
435   handle->reconnect_backoff =
436     GNUNET_TIME_STD_BACKOFF (handle->reconnect_backoff);
437   handle->reconnect_task =
438     GNUNET_SCHEDULER_add_delayed (handle->reconnect_backoff,
439                                   &reconnect_task,
440                                   handle);
441 }
442
443
444 /**
445  * Free @a it.
446  *
447  * @param it entry to free
448  */
449 static void
450 free_it (struct GNUNET_RECLAIM_AttributeIterator *it)
451 {
452   struct GNUNET_RECLAIM_Handle *h = it->h;
453
454   GNUNET_CONTAINER_DLL_remove (h->it_head, h->it_tail, it);
455   if (NULL != it->env)
456     GNUNET_MQ_discard (it->env);
457   GNUNET_free (it);
458 }
459
460
461 /**
462  * Free @a it.
463  *
464  * @param ait entry to free
465  */
466 static void
467 free_ait (struct GNUNET_RECLAIM_AttestationIterator *ait)
468 {
469   struct GNUNET_RECLAIM_Handle *h = ait->h;
470
471   GNUNET_CONTAINER_DLL_remove (h->ait_head, h->ait_tail, ait);
472   if (NULL != ait->env)
473     GNUNET_MQ_discard (ait->env);
474   GNUNET_free (ait);
475 }
476
477
478 /**
479  * Free @a op
480  *
481  * @param op the operation to free
482  */
483 static void
484 free_op (struct GNUNET_RECLAIM_Operation *op)
485 {
486   if (NULL == op)
487     return;
488   if (NULL != op->env)
489     GNUNET_MQ_discard (op->env);
490   GNUNET_free (op);
491 }
492
493
494 /**
495  * Generic error handler, called with the appropriate error code and
496  * the same closure specified at the creation of the message queue.
497  * Not every message queue implementation supports an error handler.
498  *
499  * @param cls closure with the `struct GNUNET_GNS_Handle *`
500  * @param error error code
501  */
502 static void
503 mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
504 {
505   struct GNUNET_RECLAIM_Handle *handle = cls;
506
507   force_reconnect (handle);
508 }
509
510
511 /**
512  * Handle an incoming message of type
513  * #GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE
514  *
515  * @param cls
516  * @param msg the message we received
517  */
518 static void
519 handle_success_response (void *cls, const struct SuccessResultMessage *msg)
520 {
521   struct GNUNET_RECLAIM_Handle *h = cls;
522   struct GNUNET_RECLAIM_Operation *op;
523   uint32_t r_id = ntohl (msg->id);
524   int res;
525   const char *emsg;
526
527   for (op = h->op_head; NULL != op; op = op->next)
528     if (op->r_id == r_id)
529       break;
530   if (NULL == op)
531     return;
532
533   res = ntohl (msg->op_result);
534   LOG (GNUNET_ERROR_TYPE_DEBUG,
535        "Received SUCCESS_RESPONSE with result %d\n",
536        res);
537
538   /* TODO: add actual error message to response... */
539   if (GNUNET_SYSERR == res)
540     emsg = _ ("failed to store record\n");
541   else
542     emsg = NULL;
543   if (NULL != op->as_cb)
544     op->as_cb (op->cls, res, emsg);
545   GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
546   free_op (op);
547 }
548
549
550 /**
551  * Handle an incoming message of type
552  * #GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT
553  *
554  * @param cls
555  * @param msg the message we received
556  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
557  */
558 static int
559 check_consume_ticket_result (void *cls,
560                              const struct ConsumeTicketResultMessage *msg)
561 {
562   size_t msg_len;
563   size_t attrs_len;
564
565   msg_len = ntohs (msg->header.size);
566   attrs_len = ntohs (msg->attrs_len);
567   if (msg_len != sizeof(struct ConsumeTicketResultMessage) + attrs_len)
568   {
569     GNUNET_break (0);
570     return GNUNET_SYSERR;
571   }
572   return GNUNET_OK;
573 }
574
575
576 /**
577  * Handle an incoming message of type
578  * #GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT
579  *
580  * @param cls
581  * @param msg the message we received
582  */
583 static void
584 handle_consume_ticket_result (void *cls,
585                               const struct ConsumeTicketResultMessage *msg)
586 {
587   struct GNUNET_RECLAIM_Handle *h = cls;
588   struct GNUNET_RECLAIM_Operation *op;
589   size_t attrs_len;
590   size_t attests_len;
591   uint32_t r_id = ntohl (msg->id);
592   char *read_ptr;
593
594   attrs_len = ntohs (msg->attrs_len);
595   attests_len = ntohs (msg->attestations_len);
596   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing ticket result.\n");
597
598
599   for (op = h->op_head; NULL != op; op = op->next)
600     if (op->r_id == r_id)
601       break;
602   if (NULL == op)
603     return;
604
605   {
606     struct GNUNET_RECLAIM_AttributeList *attrs;
607     struct GNUNET_RECLAIM_AttributeListEntry *le;
608     struct GNUNET_RECLAIM_AttestationList *attests;
609     struct GNUNET_RECLAIM_AttestationListEntry *ale;
610     attrs =
611       GNUNET_RECLAIM_attribute_list_deserialize ((char *) &msg[1], attrs_len);
612     read_ptr = ((char *) &msg[1]) + attrs_len;
613     attests =
614       GNUNET_RECLAIM_attestation_list_deserialize (read_ptr, attests_len);
615     if (NULL != op->atr_cb)
616     {
617       if (NULL == attrs)
618       {
619         op->atr_cb (op->cls, &msg->identity, NULL, NULL);
620       }
621       else
622       {
623         for (le = attrs->list_head; NULL != le; le = le->next)
624         {
625           if (GNUNET_NO ==
626               GNUNET_RECLAIM_id_is_zero (&le->attribute->attestation))
627           {
628             for (ale = attests->list_head; NULL != ale; ale = ale->next)
629             {
630               if (GNUNET_YES ==
631                   GNUNET_RECLAIM_id_is_equal (&le->attribute->id,
632                                               &ale->attestation->id))
633               {
634                 op->atr_cb (op->cls, &msg->identity,
635                            le->attribute, ale->attestation);
636                 break;
637               }
638
639             }
640           }
641           else     // No attestations
642           {
643             op->atr_cb (op->cls, &msg->identity,
644                        le->attribute, NULL);
645           }
646         }
647         GNUNET_RECLAIM_attribute_list_destroy (attrs);
648         GNUNET_RECLAIM_attestation_list_destroy (attests);
649         attrs = NULL;
650         attests = NULL;
651       }
652       op->atr_cb (op->cls, NULL, NULL, NULL);
653     }
654     GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
655     free_op (op);
656     GNUNET_free_non_null (attrs);
657     return;
658   }
659   GNUNET_assert (0);
660 }
661
662
663 /**
664  * Handle an incoming message of type
665  * #GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT
666  *
667  * @param cls
668  * @param msg the message we received
669  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
670  */
671 static int
672 check_attribute_result (void *cls, const struct AttributeResultMessage *msg)
673 {
674   size_t msg_len;
675   size_t attr_len;
676
677   msg_len = ntohs (msg->header.size);
678   attr_len = ntohs (msg->attr_len);
679   if (msg_len != sizeof(struct AttributeResultMessage) + attr_len)
680   {
681     GNUNET_break (0);
682     return GNUNET_SYSERR;
683   }
684   return GNUNET_OK;
685 }
686
687
688 /**
689  * Handle an incoming message of type
690  * #GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT
691  *
692  * @param cls
693  * @param msg the message we received
694  */
695 static void
696 handle_attribute_result (void *cls, const struct AttributeResultMessage *msg)
697 {
698   static struct GNUNET_CRYPTO_EcdsaPrivateKey identity_dummy;
699   struct GNUNET_RECLAIM_Handle *h = cls;
700   struct GNUNET_RECLAIM_AttributeIterator *it;
701   struct GNUNET_RECLAIM_Operation *op;
702   size_t attr_len;
703   size_t attest_len;
704   uint32_t r_id = ntohl (msg->id);
705
706   attr_len = ntohs (msg->attr_len);
707   attest_len = ntohs (msg->attestation_len);
708   LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing attribute result.\n");
709
710
711   for (it = h->it_head; NULL != it; it = it->next)
712     if (it->r_id == r_id)
713       break;
714   for (op = h->op_head; NULL != op; op = op->next)
715     if (op->r_id == r_id)
716       break;
717   if ((NULL == it) && (NULL == op))
718     return;
719
720   if ((0 ==
721        (memcmp (&msg->identity, &identity_dummy, sizeof(identity_dummy)))))
722   {
723     if ((NULL == it) && (NULL == op))
724     {
725       GNUNET_break (0);
726       force_reconnect (h);
727       return;
728     }
729     if (NULL != it)
730     {
731       if (NULL != it->finish_cb)
732         it->finish_cb (it->finish_cb_cls);
733       free_it (it);
734     }
735     if (NULL != op)
736     {
737       if (NULL != op->ar_cb)
738         op->ar_cb (op->cls, NULL, NULL);
739       GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
740       free_op (op);
741     }
742     return;
743   }
744
745   {
746     struct GNUNET_RECLAIM_Attribute *attr;
747     attr = GNUNET_RECLAIM_attribute_deserialize ((char *) &msg[1], attr_len);
748     if (NULL != it)
749     {
750       if (NULL != it->proc)
751         it->proc (it->proc_cls, &msg->identity, attr);
752     }
753     else if (NULL != op)
754     {
755       if (NULL != op->ar_cb)
756         op->ar_cb (op->cls, &msg->identity, attr);
757     }
758     GNUNET_free (attr);
759     return;
760   }
761   GNUNET_assert (0);
762 }
763
764
765 /**
766    * Handle an incoming message of type
767    * #GNUNET_MESSAGE_TYPE_RECLAIM_attestation_RESULT
768    *
769    * @param cls
770    * @param msg the message we received
771    * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
772    */
773 static int
774 check_attestation_result (void *cls, const struct AttestationResultMessage *msg)
775 {
776   size_t msg_len;
777   size_t attr_len;
778
779   msg_len = ntohs (msg->header.size);
780   attr_len = ntohs (msg->attestation_len);
781   if (msg_len != sizeof(struct AttestationResultMessage) + attr_len)
782   {
783     GNUNET_break (0);
784     return GNUNET_SYSERR;
785   }
786   return GNUNET_OK;
787 }
788
789
790 /**
791  * Handle an incoming message of type
792  * #GNUNET_MESSAGE_TYPE_RECLAIM_attestation_RESULT
793  *
794  * @param cls
795  * @param msg the message we received
796  */
797 static void
798 handle_attestation_result (void *cls, const struct
799                            AttestationResultMessage *msg)
800 {
801   static struct GNUNET_CRYPTO_EcdsaPrivateKey identity_dummy;
802   struct GNUNET_RECLAIM_Handle *h = cls;
803   struct GNUNET_RECLAIM_AttestationIterator *it;
804   struct GNUNET_RECLAIM_AttributeList *attrs;
805   struct GNUNET_RECLAIM_Operation *op;
806   size_t att_len;
807   size_t attrs_len;
808   uint32_t r_id = ntohl (msg->id);
809
810   att_len = ntohs (msg->attestation_len);
811   attrs_len = ntohs (msg->attributes_len);
812   LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing attestation result.\n");
813
814
815   for (it = h->ait_head; NULL != it; it = it->next)
816     if (it->r_id == r_id)
817       break;
818   for (op = h->op_head; NULL != op; op = op->next)
819     if (op->r_id == r_id)
820       break;
821   if ((NULL == it) && (NULL == op))
822     return;
823
824   if ((0 ==
825        (memcmp (&msg->identity, &identity_dummy, sizeof(identity_dummy)))))
826   {
827     if ((NULL == it) && (NULL == op))
828     {
829       GNUNET_break (0);
830       force_reconnect (h);
831       return;
832     }
833     if (NULL != it)
834     {
835       if (NULL != it->finish_cb)
836         it->finish_cb (it->finish_cb_cls);
837       free_ait (it);
838     }
839     if (NULL != op)
840     {
841       if (NULL != op->at_cb)
842         op->at_cb (op->cls, NULL, NULL, NULL);
843       GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
844       free_op (op);
845     }
846     return;
847   }
848
849   {
850     struct GNUNET_RECLAIM_Attestation *att;
851     att = GNUNET_RECLAIM_attestation_deserialize ((char *) &msg[1], att_len);
852     char *read_ptr = ((char *) &msg[1]) + att_len;
853     attrs = GNUNET_RECLAIM_attribute_list_deserialize (read_ptr, attrs_len);
854     if (NULL != it)
855     {
856       if (NULL != it->proc)
857         it->proc (it->proc_cls, &msg->identity, att, attrs);
858     }
859     else if (NULL != op)
860     {
861       if (NULL != op->at_cb)
862         op->at_cb (op->cls, &msg->identity, att, attrs);
863     }
864     GNUNET_free (att);
865     GNUNET_RECLAIM_attribute_list_destroy (attrs);
866     return;
867   }
868   GNUNET_assert (0);
869 }
870
871
872 /**
873  * Handle an incoming message of type
874  * #GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT
875  *
876  * @param cls
877  * @param msg the message we received
878  */
879 static void
880 handle_ticket_result (void *cls, const struct TicketResultMessage *msg)
881 {
882   struct GNUNET_RECLAIM_Handle *handle = cls;
883   struct GNUNET_RECLAIM_Operation *op;
884   struct GNUNET_RECLAIM_TicketIterator *it;
885   uint32_t r_id = ntohl (msg->id);
886   static const struct GNUNET_RECLAIM_Ticket ticket;
887
888   for (op = handle->op_head; NULL != op; op = op->next)
889     if (op->r_id == r_id)
890       break;
891   for (it = handle->ticket_it_head; NULL != it; it = it->next)
892     if (it->r_id == r_id)
893       break;
894   if ((NULL == op) && (NULL == it))
895     return;
896   if (NULL != op)
897   {
898     GNUNET_CONTAINER_DLL_remove (handle->op_head, handle->op_tail, op);
899     if (0 ==
900         memcmp (&msg->ticket, &ticket, sizeof(struct GNUNET_RECLAIM_Ticket)))
901     {
902       if (NULL != op->tr_cb)
903         op->tr_cb (op->cls, NULL);
904     }
905     else
906     {
907       if (NULL != op->tr_cb)
908         op->tr_cb (op->cls, &msg->ticket);
909     }
910     free_op (op);
911     return;
912   }
913   else if (NULL != it)
914   {
915     if (0 ==
916         memcmp (&msg->ticket, &ticket, sizeof(struct GNUNET_RECLAIM_Ticket)))
917     {
918       GNUNET_CONTAINER_DLL_remove (handle->ticket_it_head,
919                                    handle->ticket_it_tail,
920                                    it);
921       it->finish_cb (it->finish_cb_cls);
922       GNUNET_free (it);
923     }
924     else
925     {
926       if (NULL != it->tr_cb)
927         it->tr_cb (it->cls, &msg->ticket);
928     }
929     return;
930   }
931   GNUNET_break (0);
932 }
933
934
935 /**
936  * Handle an incoming message of type
937  * #GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT
938  *
939  * @param cls
940  * @param msg the message we received
941  */
942 static void
943 handle_revoke_ticket_result (void *cls,
944                              const struct RevokeTicketResultMessage *msg)
945 {
946   struct GNUNET_RECLAIM_Handle *h = cls;
947   struct GNUNET_RECLAIM_Operation *op;
948   uint32_t r_id = ntohl (msg->id);
949   int32_t success;
950
951   LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing revocation result.\n");
952
953
954   for (op = h->op_head; NULL != op; op = op->next)
955     if (op->r_id == r_id)
956       break;
957   if (NULL == op)
958     return;
959   success = ntohl (msg->success);
960   {
961     if (NULL != op->rvk_cb)
962     {
963       op->rvk_cb (op->cls, success, NULL);
964     }
965     GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
966     free_op (op);
967     return;
968   }
969   GNUNET_assert (0);
970 }
971
972
973 /**
974  * Try again to connect to the service.
975  *
976  * @param h handle to the reclaim service.
977  */
978 static void
979 reconnect (struct GNUNET_RECLAIM_Handle *h)
980 {
981   struct GNUNET_MQ_MessageHandler handlers[] =
982   { GNUNET_MQ_hd_fixed_size (success_response,
983                              GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE,
984                              struct SuccessResultMessage,
985                              h),
986     GNUNET_MQ_hd_var_size (attribute_result,
987                            GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT,
988                            struct AttributeResultMessage,
989                            h),
990     GNUNET_MQ_hd_var_size (attestation_result,
991                            GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_RESULT,
992                            struct AttestationResultMessage,
993                            h),
994     GNUNET_MQ_hd_fixed_size (ticket_result,
995                              GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT,
996                              struct TicketResultMessage,
997                              h),
998     GNUNET_MQ_hd_var_size (consume_ticket_result,
999                            GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT,
1000                            struct ConsumeTicketResultMessage,
1001                            h),
1002     GNUNET_MQ_hd_fixed_size (revoke_ticket_result,
1003                              GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT,
1004                              struct RevokeTicketResultMessage,
1005                              h),
1006     GNUNET_MQ_handler_end () };
1007   struct GNUNET_RECLAIM_Operation *op;
1008
1009   GNUNET_assert (NULL == h->mq);
1010   LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting to reclaim service.\n");
1011
1012   h->mq =
1013     GNUNET_CLIENT_connect (h->cfg, "reclaim", handlers, &mq_error_handler, h);
1014   if (NULL == h->mq)
1015     return;
1016   for (op = h->op_head; NULL != op; op = op->next)
1017     GNUNET_MQ_send_copy (h->mq, op->env);
1018 }
1019
1020
1021 /**
1022  * Connect to the reclaim service.
1023  *
1024  * @param cfg the configuration to use
1025  * @return handle to use
1026  */
1027 struct GNUNET_RECLAIM_Handle *
1028 GNUNET_RECLAIM_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
1029 {
1030   struct GNUNET_RECLAIM_Handle *h;
1031
1032   h = GNUNET_new (struct GNUNET_RECLAIM_Handle);
1033   h->cfg = cfg;
1034   reconnect (h);
1035   if (NULL == h->mq)
1036   {
1037     GNUNET_free (h);
1038     return NULL;
1039   }
1040   return h;
1041 }
1042
1043
1044 /**
1045  * Cancel an operation. Note that the operation MAY still
1046  * be executed; this merely cancels the continuation; if the request
1047  * was already transmitted, the service may still choose to complete
1048  * the operation.
1049  *
1050  * @param op operation to cancel
1051  */
1052 void
1053 GNUNET_RECLAIM_cancel (struct GNUNET_RECLAIM_Operation *op)
1054 {
1055   struct GNUNET_RECLAIM_Handle *h = op->h;
1056
1057   GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
1058   free_op (op);
1059 }
1060
1061
1062 /**
1063  * Disconnect from service
1064  *
1065  * @param h handle to destroy
1066  */
1067 void
1068 GNUNET_RECLAIM_disconnect (struct GNUNET_RECLAIM_Handle *h)
1069 {
1070   GNUNET_assert (NULL != h);
1071   if (NULL != h->mq)
1072   {
1073     GNUNET_MQ_destroy (h->mq);
1074     h->mq = NULL;
1075   }
1076   if (NULL != h->reconnect_task)
1077   {
1078     GNUNET_SCHEDULER_cancel (h->reconnect_task);
1079     h->reconnect_task = NULL;
1080   }
1081   GNUNET_assert (NULL == h->op_head);
1082   GNUNET_free (h);
1083 }
1084
1085
1086 /**
1087  * Store an attribute.  If the attribute is already present,
1088  * it is replaced with the new attribute.
1089  *
1090  * @param h handle to the re:claimID service
1091  * @param pkey private key of the identity
1092  * @param attr the attribute value
1093  * @param exp_interval the relative expiration interval for the attribute
1094  * @param cont continuation to call when done
1095  * @param cont_cls closure for @a cont
1096  * @return handle to abort the request
1097  */
1098 struct GNUNET_RECLAIM_Operation *
1099 GNUNET_RECLAIM_attribute_store (
1100   struct GNUNET_RECLAIM_Handle *h,
1101   const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
1102   const struct GNUNET_RECLAIM_Attribute *attr,
1103   const struct GNUNET_TIME_Relative *exp_interval,
1104   GNUNET_RECLAIM_ContinuationWithStatus cont,
1105   void *cont_cls)
1106 {
1107   struct GNUNET_RECLAIM_Operation *op;
1108   struct AttributeStoreMessage *sam;
1109   size_t attr_len;
1110
1111   op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1112   op->h = h;
1113   op->as_cb = cont;
1114   op->cls = cont_cls;
1115   op->r_id = h->r_id_gen++;
1116   GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1117   attr_len = GNUNET_RECLAIM_attribute_serialize_get_size (attr);
1118   op->env = GNUNET_MQ_msg_extra (sam,
1119                                  attr_len,
1120                                  GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE);
1121   sam->identity = *pkey;
1122   sam->id = htonl (op->r_id);
1123   sam->exp = GNUNET_htonll (exp_interval->rel_value_us);
1124
1125   GNUNET_RECLAIM_attribute_serialize (attr, (char *) &sam[1]);
1126
1127   sam->attr_len = htons (attr_len);
1128   if (NULL != h->mq)
1129     GNUNET_MQ_send_copy (h->mq, op->env);
1130   return op;
1131 }
1132
1133
1134 /**
1135  * Delete an attribute. Tickets used to share this attribute are updated
1136  * accordingly.
1137  *
1138  * @param h handle to the re:claimID service
1139  * @param pkey Private key of the identity to add an attribute to
1140  * @param attr The attribute
1141  * @param cont Continuation to call when done
1142  * @param cont_cls Closure for @a cont
1143  * @return handle Used to to abort the request
1144  */
1145 struct GNUNET_RECLAIM_Operation *
1146 GNUNET_RECLAIM_attribute_delete (
1147   struct GNUNET_RECLAIM_Handle *h,
1148   const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
1149   const struct GNUNET_RECLAIM_Attribute *attr,
1150   GNUNET_RECLAIM_ContinuationWithStatus cont,
1151   void *cont_cls)
1152 {
1153   struct GNUNET_RECLAIM_Operation *op;
1154   struct AttributeDeleteMessage *dam;
1155   size_t attr_len;
1156
1157   op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1158   op->h = h;
1159   op->as_cb = cont;
1160   op->cls = cont_cls;
1161   op->r_id = h->r_id_gen++;
1162   GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1163   attr_len = GNUNET_RECLAIM_attribute_serialize_get_size (attr);
1164   op->env = GNUNET_MQ_msg_extra (dam,
1165                                  attr_len,
1166                                  GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_DELETE);
1167   dam->identity = *pkey;
1168   dam->id = htonl (op->r_id);
1169   GNUNET_RECLAIM_attribute_serialize (attr, (char *) &dam[1]);
1170
1171   dam->attr_len = htons (attr_len);
1172   if (NULL != h->mq)
1173     GNUNET_MQ_send_copy (h->mq, op->env);
1174   return op;
1175 }
1176
1177
1178 /**
1179    * Store an attestation.  If the attestation is already present,
1180    * it is replaced with the new attestation.
1181    *
1182    * @param h handle to the re:claimID service
1183    * @param pkey private key of the identity
1184    * @param attr the attestation value
1185    * @param exp_interval the relative expiration interval for the attestation
1186    * @param cont continuation to call when done
1187    * @param cont_cls closure for @a cont
1188    * @return handle to abort the request
1189    */
1190 struct GNUNET_RECLAIM_Operation *
1191 GNUNET_RECLAIM_attestation_store (
1192   struct GNUNET_RECLAIM_Handle *h,
1193   const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
1194   const struct GNUNET_RECLAIM_Attestation *attr,
1195   const struct GNUNET_TIME_Relative *exp_interval,
1196   GNUNET_RECLAIM_ContinuationWithStatus cont,
1197   void *cont_cls)
1198 {
1199   struct GNUNET_RECLAIM_Operation *op;
1200   struct AttributeStoreMessage *sam;
1201   size_t attr_len;
1202
1203   op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1204   op->h = h;
1205   op->as_cb = cont;
1206   op->cls = cont_cls;
1207   op->r_id = h->r_id_gen++;
1208   GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1209   attr_len = GNUNET_RECLAIM_attestation_serialize_get_size (attr);
1210   op->env = GNUNET_MQ_msg_extra (sam,
1211                                  attr_len,
1212                                  GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_STORE);
1213   sam->identity = *pkey;
1214   sam->id = htonl (op->r_id);
1215   sam->exp = GNUNET_htonll (exp_interval->rel_value_us);
1216
1217   GNUNET_RECLAIM_attestation_serialize (attr, (char *) &sam[1]);
1218
1219   sam->attr_len = htons (attr_len);
1220   if (NULL != h->mq)
1221     GNUNET_MQ_send_copy (h->mq, op->env);
1222   return op;
1223 }
1224
1225
1226 /**
1227    * Delete an attestation. Tickets used to share this attestation are updated
1228    * accordingly.
1229    *
1230    * @param h handle to the re:claimID service
1231    * @param pkey Private key of the identity to add an attribute to
1232    * @param attr The attestation
1233    * @param cont Continuation to call when done
1234    * @param cont_cls Closure for @a cont
1235    * @return handle Used to to abort the request
1236    */
1237 struct GNUNET_RECLAIM_Operation *
1238 GNUNET_RECLAIM_attestation_delete (
1239   struct GNUNET_RECLAIM_Handle *h,
1240   const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
1241   const struct GNUNET_RECLAIM_Attestation *attr,
1242   GNUNET_RECLAIM_ContinuationWithStatus cont,
1243   void *cont_cls)
1244 {
1245   struct GNUNET_RECLAIM_Operation *op;
1246   struct AttributeDeleteMessage *dam;
1247   size_t attr_len;
1248
1249   op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1250   op->h = h;
1251   op->as_cb = cont;
1252   op->cls = cont_cls;
1253   op->r_id = h->r_id_gen++;
1254   GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1255   attr_len = GNUNET_RECLAIM_attestation_serialize_get_size (attr);
1256   op->env = GNUNET_MQ_msg_extra (dam,
1257                                  attr_len,
1258                                  GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_DELETE);
1259   dam->identity = *pkey;
1260   dam->id = htonl (op->r_id);
1261   GNUNET_RECLAIM_attestation_serialize (attr, (char *) &dam[1]);
1262
1263   dam->attr_len = htons (attr_len);
1264   if (NULL != h->mq)
1265     GNUNET_MQ_send_copy (h->mq, op->env);
1266   return op;
1267 }
1268
1269
1270 /**
1271  * List all attributes for a local identity.
1272  * This MUST lock the `struct GNUNET_RECLAIM_Handle`
1273  * for any other calls than #GNUNET_RECLAIM_get_attributes_next() and
1274  * #GNUNET_RECLAIM_get_attributes_stop. @a proc will be called once
1275  * immediately, and then again after
1276  * #GNUNET_RECLAIM_get_attributes_next() is invoked.
1277  *
1278  * On error (disconnect), @a error_cb will be invoked.
1279  * On normal completion, @a finish_cb proc will be
1280  * invoked.
1281  *
1282  * @param h Handle to the re:claimID service
1283  * @param identity Identity to iterate over
1284  * @param error_cb Function to call on error (i.e. disconnect),
1285  *        the handle is afterwards invalid
1286  * @param error_cb_cls Closure for @a error_cb
1287  * @param proc Function to call on each attribute
1288  * @param proc_cls Closure for @a proc
1289  * @param finish_cb Function to call on completion
1290  *        the handle is afterwards invalid
1291  * @param finish_cb_cls Closure for @a finish_cb
1292  * @return an iterator Handle to use for iteration
1293  */
1294 struct GNUNET_RECLAIM_AttributeIterator *
1295 GNUNET_RECLAIM_get_attributes_start (
1296   struct GNUNET_RECLAIM_Handle *h,
1297   const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
1298   GNUNET_SCHEDULER_TaskCallback error_cb,
1299   void *error_cb_cls,
1300   GNUNET_RECLAIM_AttributeResult proc,
1301   void *proc_cls,
1302   GNUNET_SCHEDULER_TaskCallback finish_cb,
1303   void *finish_cb_cls)
1304 {
1305   struct GNUNET_RECLAIM_AttributeIterator *it;
1306   struct GNUNET_MQ_Envelope *env;
1307   struct AttributeIterationStartMessage *msg;
1308   uint32_t rid;
1309
1310   rid = h->r_id_gen++;
1311   it = GNUNET_new (struct GNUNET_RECLAIM_AttributeIterator);
1312   it->h = h;
1313   it->error_cb = error_cb;
1314   it->error_cb_cls = error_cb_cls;
1315   it->finish_cb = finish_cb;
1316   it->finish_cb_cls = finish_cb_cls;
1317   it->proc = proc;
1318   it->proc_cls = proc_cls;
1319   it->r_id = rid;
1320   it->identity = *identity;
1321   GNUNET_CONTAINER_DLL_insert_tail (h->it_head, h->it_tail, it);
1322   env =
1323     GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_START);
1324   msg->id = htonl (rid);
1325   msg->identity = *identity;
1326   if (NULL == h->mq)
1327     it->env = env;
1328   else
1329     GNUNET_MQ_send (h->mq, env);
1330   return it;
1331 }
1332
1333
1334 /**
1335  * Calls the record processor specified in #GNUNET_RECLAIM_get_attributes_start
1336  * for the next record.
1337  *
1338  * @param it the iterator
1339  */
1340 void
1341 GNUNET_RECLAIM_get_attributes_next (struct GNUNET_RECLAIM_AttributeIterator *it)
1342 {
1343   struct GNUNET_RECLAIM_Handle *h = it->h;
1344   struct AttributeIterationNextMessage *msg;
1345   struct GNUNET_MQ_Envelope *env;
1346
1347   env =
1348     GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT);
1349   msg->id = htonl (it->r_id);
1350   GNUNET_MQ_send (h->mq, env);
1351 }
1352
1353
1354 /**
1355  * Stops iteration and releases the handle for further calls. Must
1356  * be called on any iteration that has not yet completed prior to calling
1357  * #GNUNET_RECLAIM_disconnect.
1358  *
1359  * @param it the iterator
1360  */
1361 void
1362 GNUNET_RECLAIM_get_attributes_stop (struct GNUNET_RECLAIM_AttributeIterator *it)
1363 {
1364   struct GNUNET_RECLAIM_Handle *h = it->h;
1365   struct GNUNET_MQ_Envelope *env;
1366   struct AttributeIterationStopMessage *msg;
1367
1368   if (NULL != h->mq)
1369   {
1370     env =
1371       GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP);
1372     msg->id = htonl (it->r_id);
1373     GNUNET_MQ_send (h->mq, env);
1374   }
1375   free_it (it);
1376 }
1377
1378
1379 /**
1380  * List all attestations for a local identity.
1381  * This MUST lock the `struct GNUNET_RECLAIM_Handle`
1382  * for any other calls than #GNUNET_RECLAIM_get_attestations_next() and
1383  * #GNUNET_RECLAIM_get_attestations_stop. @a proc will be called once
1384  * immediately, and then again after
1385  * #GNUNET_RECLAIM_get_attestations_next() is invoked.
1386  *
1387  * On error (disconnect), @a error_cb will be invoked.
1388  * On normal completion, @a finish_cb proc will be
1389  * invoked.
1390  *
1391  * @param h Handle to the re:claimID service
1392  * @param identity Identity to iterate over
1393  * @param error_cb Function to call on error (i.e. disconnect),
1394  *        the handle is afterwards invalid
1395  * @param error_cb_cls Closure for @a error_cb
1396  * @param proc Function to call on each attestation
1397  * @param proc_cls Closure for @a proc
1398  * @param finish_cb Function to call on completion
1399  *        the handle is afterwards invalid
1400  * @param finish_cb_cls Closure for @a finish_cb
1401  * @return an iterator Handle to use for iteration
1402  */
1403 struct GNUNET_RECLAIM_AttestationIterator *
1404 GNUNET_RECLAIM_get_attestations_start (
1405   struct GNUNET_RECLAIM_Handle *h,
1406   const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
1407   GNUNET_SCHEDULER_TaskCallback error_cb,
1408   void *error_cb_cls,
1409   GNUNET_RECLAIM_AttestationResult proc,
1410   void *proc_cls,
1411   GNUNET_SCHEDULER_TaskCallback finish_cb,
1412   void *finish_cb_cls)
1413 {
1414   struct GNUNET_RECLAIM_AttestationIterator *ait;
1415   struct GNUNET_MQ_Envelope *env;
1416   struct AttestationIterationStartMessage *msg;
1417   uint32_t rid;
1418
1419   rid = h->r_id_gen++;
1420   ait = GNUNET_new (struct GNUNET_RECLAIM_AttestationIterator);
1421   ait->h = h;
1422   ait->error_cb = error_cb;
1423   ait->error_cb_cls = error_cb_cls;
1424   ait->finish_cb = finish_cb;
1425   ait->finish_cb_cls = finish_cb_cls;
1426   ait->proc = proc;
1427   ait->proc_cls = proc_cls;
1428   ait->r_id = rid;
1429   ait->identity = *identity;
1430   GNUNET_CONTAINER_DLL_insert_tail (h->ait_head, h->ait_tail, ait);
1431   env =
1432     GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_START);
1433   msg->id = htonl (rid);
1434   msg->identity = *identity;
1435   if (NULL == h->mq)
1436     ait->env = env;
1437   else
1438     GNUNET_MQ_send (h->mq, env);
1439   return ait;
1440 }
1441
1442
1443 /**
1444  * Calls the record processor specified in #GNUNET_RECLAIM_get_attestation_start
1445  * for the next record.
1446  *
1447  * @param it the iterator
1448  */
1449 void
1450 GNUNET_RECLAIM_get_attestations_next (struct GNUNET_RECLAIM_AttestationIterator *ait)
1451 {
1452   struct GNUNET_RECLAIM_Handle *h = ait->h;
1453   struct AttestationIterationNextMessage *msg;
1454   struct GNUNET_MQ_Envelope *env;
1455
1456   env =
1457     GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_NEXT);
1458   msg->id = htonl (ait->r_id);
1459   GNUNET_MQ_send (h->mq, env);
1460 }
1461
1462
1463 /**
1464  * Stops iteration and releases the handle for further calls. Must
1465  * be called on any iteration that has not yet completed prior to calling
1466  * #GNUNET_RECLAIM_disconnect.
1467  *
1468  * @param it the iterator
1469  */
1470 void
1471 GNUNET_RECLAIM_get_attestations_stop (struct GNUNET_RECLAIM_AttestationIterator *ait)
1472 {
1473   struct GNUNET_RECLAIM_Handle *h = ait->h;
1474   struct GNUNET_MQ_Envelope *env;
1475   struct AttestationIterationStopMessage *msg;
1476
1477   if (NULL != h->mq)
1478   {
1479     env =
1480       GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_ATTESTATION_ITERATION_STOP);
1481     msg->id = htonl (ait->r_id);
1482     GNUNET_MQ_send (h->mq, env);
1483   }
1484   free_ait (ait);
1485 }
1486
1487
1488
1489 /**
1490  * Issues a ticket to another relying party. The identity may use
1491  * @GNUNET_RECLAIM_ticket_consume to consume the ticket
1492  * and retrieve the attributes specified in the attribute list.
1493  *
1494  * @param h the reclaim to use
1495  * @param iss the issuing identity (= the user)
1496  * @param rp the subject of the ticket (= the relying party)
1497  * @param attrs the attributes that the relying party is given access to
1498  * @param cb the callback
1499  * @param cb_cls the callback closure
1500  * @return handle to abort the operation
1501  */
1502 struct GNUNET_RECLAIM_Operation *
1503 GNUNET_RECLAIM_ticket_issue (
1504   struct GNUNET_RECLAIM_Handle *h,
1505   const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss,
1506   const struct GNUNET_CRYPTO_EcdsaPublicKey *rp,
1507   const struct GNUNET_RECLAIM_AttributeList *attrs,
1508   GNUNET_RECLAIM_TicketCallback cb,
1509   void *cb_cls)
1510 {
1511   struct GNUNET_RECLAIM_Operation *op;
1512   struct IssueTicketMessage *tim;
1513   size_t attr_len;
1514
1515   fprintf (stderr, "Issuing ticket\n");
1516   op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1517   op->h = h;
1518   op->tr_cb = cb;
1519   op->cls = cb_cls;
1520   op->r_id = h->r_id_gen++;
1521   GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1522   attr_len = GNUNET_RECLAIM_attribute_list_serialize_get_size (attrs);
1523   op->env = GNUNET_MQ_msg_extra (tim,
1524                                  attr_len,
1525                                  GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET);
1526   tim->identity = *iss;
1527   tim->rp = *rp;
1528   tim->id = htonl (op->r_id);
1529
1530   GNUNET_RECLAIM_attribute_list_serialize (attrs, (char *) &tim[1]);
1531
1532   tim->attr_len = htons (attr_len);
1533   if (NULL != h->mq)
1534     GNUNET_MQ_send_copy (h->mq, op->env);
1535   return op;
1536 }
1537
1538
1539 /**
1540  * Consumes an issued ticket. The ticket is persisted
1541  * and used to retrieve identity information from the issuer
1542  *
1543  * @param h the reclaim to use
1544  * @param identity the identity that is the subject of the issued ticket (the
1545  * relying party)
1546  * @param ticket the issued ticket to consume
1547  * @param cb the callback to call
1548  * @param cb_cls the callback closure
1549  * @return handle to abort the operation
1550  */
1551 struct GNUNET_RECLAIM_Operation *
1552 GNUNET_RECLAIM_ticket_consume (
1553   struct GNUNET_RECLAIM_Handle *h,
1554   const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
1555   const struct GNUNET_RECLAIM_Ticket *ticket,
1556   GNUNET_RECLAIM_AttributeTicketResult cb,
1557   void *cb_cls)
1558 {
1559   struct GNUNET_RECLAIM_Operation *op;
1560   struct ConsumeTicketMessage *ctm;
1561
1562   op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1563   op->h = h;
1564   op->atr_cb = cb;
1565   op->cls = cb_cls;
1566   op->r_id = h->r_id_gen++;
1567   GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1568   op->env = GNUNET_MQ_msg (ctm, GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET);
1569   ctm->identity = *identity;
1570   ctm->id = htonl (op->r_id);
1571   ctm->ticket = *ticket;
1572   if (NULL != h->mq)
1573     GNUNET_MQ_send_copy (h->mq, op->env);
1574   return op;
1575 }
1576
1577
1578 /**
1579  * Lists all tickets that have been issued to remote
1580  * identites (relying parties)
1581  *
1582  * @param h the reclaim to use
1583  * @param identity the issuing identity
1584  * @param error_cb function to call on error (i.e. disconnect),
1585  *        the handle is afterwards invalid
1586  * @param error_cb_cls closure for @a error_cb
1587  * @param proc function to call on each ticket; it
1588  *        will be called repeatedly with a value (if available)
1589  * @param proc_cls closure for @a proc
1590  * @param finish_cb function to call on completion
1591  *        the handle is afterwards invalid
1592  * @param finish_cb_cls closure for @a finish_cb
1593  * @return an iterator handle to use for iteration
1594  */
1595 struct GNUNET_RECLAIM_TicketIterator *
1596 GNUNET_RECLAIM_ticket_iteration_start (
1597   struct GNUNET_RECLAIM_Handle *h,
1598   const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
1599   GNUNET_SCHEDULER_TaskCallback error_cb,
1600   void *error_cb_cls,
1601   GNUNET_RECLAIM_TicketCallback proc,
1602   void *proc_cls,
1603   GNUNET_SCHEDULER_TaskCallback finish_cb,
1604   void *finish_cb_cls)
1605 {
1606   struct GNUNET_RECLAIM_TicketIterator *it;
1607   struct GNUNET_MQ_Envelope *env;
1608   struct TicketIterationStartMessage *msg;
1609   uint32_t rid;
1610
1611   rid = h->r_id_gen++;
1612   it = GNUNET_new (struct GNUNET_RECLAIM_TicketIterator);
1613   it->h = h;
1614   it->error_cb = error_cb;
1615   it->error_cb_cls = error_cb_cls;
1616   it->finish_cb = finish_cb;
1617   it->finish_cb_cls = finish_cb_cls;
1618   it->tr_cb = proc;
1619   it->cls = proc_cls;
1620   it->r_id = rid;
1621   GNUNET_CONTAINER_DLL_insert_tail (h->ticket_it_head, h->ticket_it_tail, it);
1622   env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_START);
1623   msg->id = htonl (rid);
1624   msg->identity = *identity;
1625   if (NULL == h->mq)
1626     it->env = env;
1627   else
1628     GNUNET_MQ_send (h->mq, env);
1629   return it;
1630 }
1631
1632
1633 /**
1634  * Calls the ticket processor specified in
1635  * #GNUNET_RECLAIM_ticket_iteration_start for the next record.
1636  *
1637  * @param it the iterator
1638  */
1639 void
1640 GNUNET_RECLAIM_ticket_iteration_next (struct GNUNET_RECLAIM_TicketIterator *it)
1641 {
1642   struct GNUNET_RECLAIM_Handle *h = it->h;
1643   struct TicketIterationNextMessage *msg;
1644   struct GNUNET_MQ_Envelope *env;
1645
1646   env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_NEXT);
1647   msg->id = htonl (it->r_id);
1648   GNUNET_MQ_send (h->mq, env);
1649 }
1650
1651
1652 /**
1653  * Stops iteration and releases the handle for further calls.  Must
1654  * be called on any iteration that has not yet completed prior to calling
1655  * #GNUNET_RECLAIM_disconnect.
1656  *
1657  * @param it the iterator
1658  */
1659 void
1660 GNUNET_RECLAIM_ticket_iteration_stop (struct GNUNET_RECLAIM_TicketIterator *it)
1661 {
1662   struct GNUNET_RECLAIM_Handle *h = it->h;
1663   struct GNUNET_MQ_Envelope *env;
1664   struct TicketIterationStopMessage *msg;
1665
1666   if (NULL != h->mq)
1667   {
1668     env =
1669       GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_STOP);
1670     msg->id = htonl (it->r_id);
1671     GNUNET_MQ_send (h->mq, env);
1672   }
1673   GNUNET_free (it);
1674 }
1675
1676
1677 /**
1678  * Revoked an issued ticket. The relying party will be unable to retrieve
1679  * attributes. Other issued tickets remain unaffected.
1680  * This includes tickets issued to other relying parties as well as to
1681  * other tickets issued to the audience specified in this ticket.
1682  *
1683  * @param h the identity provider to use
1684  * @param identity the issuing identity
1685  * @param ticket the ticket to revoke
1686  * @param cb the callback
1687  * @param cb_cls the callback closure
1688  * @return handle to abort the operation
1689  */
1690 struct GNUNET_RECLAIM_Operation *
1691 GNUNET_RECLAIM_ticket_revoke (
1692   struct GNUNET_RECLAIM_Handle *h,
1693   const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
1694   const struct GNUNET_RECLAIM_Ticket *ticket,
1695   GNUNET_RECLAIM_ContinuationWithStatus cb,
1696   void *cb_cls)
1697 {
1698   struct GNUNET_RECLAIM_Operation *op;
1699   struct RevokeTicketMessage *msg;
1700   uint32_t rid;
1701
1702   rid = h->r_id_gen++;
1703   op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1704   op->h = h;
1705   op->rvk_cb = cb;
1706   op->cls = cb_cls;
1707   op->r_id = rid;
1708   GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1709   op->env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET);
1710   msg->id = htonl (rid);
1711   msg->identity = *identity;
1712   msg->ticket = *ticket;
1713   if (NULL != h->mq)
1714   {
1715     GNUNET_MQ_send (h->mq, op->env);
1716     op->env = NULL;
1717   }
1718   return op;
1719 }
1720
1721
1722 /* end of reclaim_api.c */