better debug output
[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   /**
45    * Main handle.
46    */
47   struct GNUNET_RECLAIM_Handle *h;
48
49   /**
50    * We keep operations in a DLL.
51    */
52   struct GNUNET_RECLAIM_Operation *next;
53
54   /**
55    * We keep operations in a DLL.
56    */
57   struct GNUNET_RECLAIM_Operation *prev;
58
59   /**
60    * Message to send to the service.
61    * Allocated at the end of this struct.
62    */
63   const struct GNUNET_MessageHeader *msg;
64
65   /**
66    * Continuation to invoke after attribute store call
67    */
68   GNUNET_RECLAIM_ContinuationWithStatus as_cb;
69
70   /**
71    * Attribute result callback
72    */
73   GNUNET_RECLAIM_AttributeResult ar_cb;
74
75   /**
76    * Revocation result callback
77    */
78   GNUNET_RECLAIM_ContinuationWithStatus rvk_cb;
79
80   /**
81    * Ticket result callback
82    */
83   GNUNET_RECLAIM_TicketCallback tr_cb;
84
85   /**
86    * Envelope with the message for this queue entry.
87    */
88   struct GNUNET_MQ_Envelope *env;
89
90   /**
91    * request id
92    */
93   uint32_t r_id;
94
95   /**
96    * Closure for @e cont or @e cb.
97    */
98   void *cls;
99 };
100
101
102 /**
103  * Handle for a ticket iterator operation
104  */
105 struct GNUNET_RECLAIM_TicketIterator
106 {
107
108   /**
109    * Kept in a DLL.
110    */
111   struct GNUNET_RECLAIM_TicketIterator *next;
112
113   /**
114    * Kept in a DLL.
115    */
116   struct GNUNET_RECLAIM_TicketIterator *prev;
117
118   /**
119    * Main handle to access the idp.
120    */
121   struct GNUNET_RECLAIM_Handle *h;
122
123   /**
124    * Function to call on completion.
125    */
126   GNUNET_SCHEDULER_TaskCallback finish_cb;
127
128   /**
129    * Closure for @e finish_cb.
130    */
131   void *finish_cb_cls;
132
133   /**
134    * The continuation to call with the results
135    */
136   GNUNET_RECLAIM_TicketCallback tr_cb;
137
138   /**
139    * Closure for @e tr_cb.
140    */
141   void *cls;
142
143   /**
144    * Function to call on errors.
145    */
146   GNUNET_SCHEDULER_TaskCallback error_cb;
147
148   /**
149    * Closure for @e error_cb.
150    */
151   void *error_cb_cls;
152
153   /**
154    * Envelope of the message to send to the service, if not yet
155    * sent.
156    */
157   struct GNUNET_MQ_Envelope *env;
158
159   /**
160    * The operation id this zone iteration operation has
161    */
162   uint32_t r_id;
163 };
164
165
166 /**
167  * Handle for a attribute iterator operation
168  */
169 struct GNUNET_RECLAIM_AttributeIterator
170 {
171
172   /**
173    * Kept in a DLL.
174    */
175   struct GNUNET_RECLAIM_AttributeIterator *next;
176
177   /**
178    * Kept in a DLL.
179    */
180   struct GNUNET_RECLAIM_AttributeIterator *prev;
181
182   /**
183    * Main handle to access the service.
184    */
185   struct GNUNET_RECLAIM_Handle *h;
186
187   /**
188    * Function to call on completion.
189    */
190   GNUNET_SCHEDULER_TaskCallback finish_cb;
191
192   /**
193    * Closure for @e finish_cb.
194    */
195   void *finish_cb_cls;
196
197   /**
198    * The continuation to call with the results
199    */
200   GNUNET_RECLAIM_AttributeResult proc;
201
202   /**
203    * Closure for @e proc.
204    */
205   void *proc_cls;
206
207   /**
208    * Function to call on errors.
209    */
210   GNUNET_SCHEDULER_TaskCallback error_cb;
211
212   /**
213    * Closure for @e error_cb.
214    */
215   void *error_cb_cls;
216
217   /**
218    * Envelope of the message to send to the service, if not yet
219    * sent.
220    */
221   struct GNUNET_MQ_Envelope *env;
222
223   /**
224    * Private key of the zone.
225    */
226   struct GNUNET_CRYPTO_EcdsaPrivateKey identity;
227
228   /**
229    * The operation id this zone iteration operation has
230    */
231   uint32_t r_id;
232 };
233
234
235 /**
236  * Handle to the service.
237  */
238 struct GNUNET_RECLAIM_Handle
239 {
240   /**
241    * Configuration to use.
242    */
243   const struct GNUNET_CONFIGURATION_Handle *cfg;
244
245   /**
246    * Socket (if available).
247    */
248   struct GNUNET_CLIENT_Connection *client;
249
250   /**
251    * Closure for 'cb'.
252    */
253   void *cb_cls;
254
255   /**
256    * Head of active operations.
257    */
258   struct GNUNET_RECLAIM_Operation *op_head;
259
260   /**
261    * Tail of active operations.
262    */
263   struct GNUNET_RECLAIM_Operation *op_tail;
264
265   /**
266    * Head of active iterations
267    */
268   struct GNUNET_RECLAIM_AttributeIterator *it_head;
269
270   /**
271    * Tail of active iterations
272    */
273   struct GNUNET_RECLAIM_AttributeIterator *it_tail;
274
275   /**
276    * Head of active iterations
277    */
278   struct GNUNET_RECLAIM_TicketIterator *ticket_it_head;
279
280   /**
281    * Tail of active iterations
282    */
283   struct GNUNET_RECLAIM_TicketIterator *ticket_it_tail;
284
285   /**
286    * Currently pending transmission request, or NULL for none.
287    */
288   struct GNUNET_CLIENT_TransmitHandle *th;
289
290   /**
291    * Task doing exponential back-off trying to reconnect.
292    */
293   struct GNUNET_SCHEDULER_Task *reconnect_task;
294
295   /**
296    * Time for next connect retry.
297    */
298   struct GNUNET_TIME_Relative reconnect_backoff;
299
300   /**
301    * Connection to service (if available).
302    */
303   struct GNUNET_MQ_Handle *mq;
304
305   /**
306    * Request Id generator.  Incremented by one for each request.
307    */
308   uint32_t r_id_gen;
309
310   /**
311    * Are we polling for incoming messages right now?
312    */
313   int in_receive;
314 };
315
316
317 /**
318  * Try again to connect to the service.
319  *
320  * @param h handle to the reclaim service.
321  */
322 static void
323 reconnect (struct GNUNET_RECLAIM_Handle *h);
324
325
326 /**
327  * Reconnect
328  *
329  * @param cls the handle
330  */
331 static void
332 reconnect_task (void *cls)
333 {
334   struct GNUNET_RECLAIM_Handle *handle = cls;
335
336   handle->reconnect_task = NULL;
337   reconnect (handle);
338 }
339
340
341 /**
342  * Disconnect from service and then reconnect.
343  *
344  * @param handle our service
345  */
346 static void
347 force_reconnect (struct GNUNET_RECLAIM_Handle *handle)
348 {
349   GNUNET_MQ_destroy (handle->mq);
350   handle->mq = NULL;
351   handle->reconnect_backoff =
352     GNUNET_TIME_STD_BACKOFF (handle->reconnect_backoff);
353   handle->reconnect_task =
354     GNUNET_SCHEDULER_add_delayed (handle->reconnect_backoff,
355                                   &reconnect_task,
356                                   handle);
357 }
358
359
360 /**
361  * Free @a it.
362  *
363  * @param it entry to free
364  */
365 static void
366 free_it (struct GNUNET_RECLAIM_AttributeIterator *it)
367 {
368   struct GNUNET_RECLAIM_Handle *h = it->h;
369
370   GNUNET_CONTAINER_DLL_remove (h->it_head, h->it_tail, it);
371   if (NULL != it->env)
372     GNUNET_MQ_discard (it->env);
373   GNUNET_free (it);
374 }
375
376 /**
377  * Free @a op
378  *
379  * @param op the operation to free
380  */
381 static void
382 free_op (struct GNUNET_RECLAIM_Operation *op)
383 {
384   if (NULL == op)
385     return;
386   if (NULL != op->env)
387     GNUNET_MQ_discard (op->env);
388   GNUNET_free (op);
389 }
390
391
392 /**
393  * Generic error handler, called with the appropriate error code and
394  * the same closure specified at the creation of the message queue.
395  * Not every message queue implementation supports an error handler.
396  *
397  * @param cls closure with the `struct GNUNET_GNS_Handle *`
398  * @param error error code
399  */
400 static void
401 mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
402 {
403   struct GNUNET_RECLAIM_Handle *handle = cls;
404   force_reconnect (handle);
405 }
406
407
408 /**
409  * Handle an incoming message of type
410  * #GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE
411  *
412  * @param cls
413  * @param msg the message we received
414  */
415 static void
416 handle_success_response (void *cls, const struct SuccessResultMessage *msg)
417 {
418   struct GNUNET_RECLAIM_Handle *h = cls;
419   struct GNUNET_RECLAIM_Operation *op;
420   uint32_t r_id = ntohl (msg->id);
421   int res;
422   const char *emsg;
423
424   for (op = h->op_head; NULL != op; op = op->next)
425     if (op->r_id == r_id)
426       break;
427   if (NULL == op)
428     return;
429
430   res = ntohl (msg->op_result);
431   LOG (GNUNET_ERROR_TYPE_DEBUG,
432        "Received SUCCESS_RESPONSE with result %d\n",
433        res);
434
435   /* TODO: add actual error message to response... */
436   if (GNUNET_SYSERR == res)
437     emsg = _ ("failed to store record\n");
438   else
439     emsg = NULL;
440   if (NULL != op->as_cb)
441     op->as_cb (op->cls, res, emsg);
442   GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
443   free_op (op);
444 }
445
446
447 /**
448  * Handle an incoming message of type
449  * #GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT
450  *
451  * @param cls
452  * @param msg the message we received
453  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
454  */
455 static int
456 check_consume_ticket_result (void *cls,
457                              const struct ConsumeTicketResultMessage *msg)
458 {
459   size_t msg_len;
460   size_t attrs_len;
461
462   msg_len = ntohs (msg->header.size);
463   attrs_len = ntohs (msg->attrs_len);
464   if (msg_len != sizeof (struct ConsumeTicketResultMessage) + attrs_len)
465   {
466     GNUNET_break (0);
467     return GNUNET_SYSERR;
468   }
469   return GNUNET_OK;
470 }
471
472
473 /**
474  * Handle an incoming message of type
475  * #GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT
476  *
477  * @param cls
478  * @param msg the message we received
479  */
480 static void
481 handle_consume_ticket_result (void *cls,
482                               const struct ConsumeTicketResultMessage *msg)
483 {
484   struct GNUNET_RECLAIM_Handle *h = cls;
485   struct GNUNET_RECLAIM_Operation *op;
486   size_t attrs_len;
487   uint32_t r_id = ntohl (msg->id);
488
489   attrs_len = ntohs (msg->attrs_len);
490   LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing attribute result.\n");
491
492
493   for (op = h->op_head; NULL != op; op = op->next)
494     if (op->r_id == r_id)
495       break;
496   if (NULL == op)
497     return;
498
499   {
500     struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs;
501     struct GNUNET_RECLAIM_ATTRIBUTE_ClaimListEntry *le;
502     attrs =
503       GNUNET_RECLAIM_ATTRIBUTE_list_deserialize ((char *) &msg[1], attrs_len);
504     if (NULL != op->ar_cb)
505     {
506       if (NULL == attrs)
507       {
508         op->ar_cb (op->cls, &msg->identity, NULL);
509       }
510       else
511       {
512         for (le = attrs->list_head; NULL != le; le = le->next)
513           op->ar_cb (op->cls, &msg->identity, le->claim);
514         GNUNET_RECLAIM_ATTRIBUTE_list_destroy (attrs);
515         attrs = NULL;
516       }
517       op->ar_cb (op->cls, NULL, NULL);
518     }
519     GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
520     free_op (op);
521     GNUNET_free_non_null (attrs);
522     return;
523   }
524   GNUNET_assert (0);
525 }
526
527
528 /**
529  * Handle an incoming message of type
530  * #GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT
531  *
532  * @param cls
533  * @param msg the message we received
534  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
535  */
536 static int
537 check_attribute_result (void *cls, const struct AttributeResultMessage *msg)
538 {
539   size_t msg_len;
540   size_t attr_len;
541
542   msg_len = ntohs (msg->header.size);
543   attr_len = ntohs (msg->attr_len);
544   if (msg_len != sizeof (struct AttributeResultMessage) + attr_len)
545   {
546     GNUNET_break (0);
547     return GNUNET_SYSERR;
548   }
549   return GNUNET_OK;
550 }
551
552
553 /**
554  * Handle an incoming message of type
555  * #GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT
556  *
557  * @param cls
558  * @param msg the message we received
559  */
560 static void
561 handle_attribute_result (void *cls, const struct AttributeResultMessage *msg)
562 {
563   static struct GNUNET_CRYPTO_EcdsaPrivateKey identity_dummy;
564   struct GNUNET_RECLAIM_Handle *h = cls;
565   struct GNUNET_RECLAIM_AttributeIterator *it;
566   struct GNUNET_RECLAIM_Operation *op;
567   size_t attr_len;
568   uint32_t r_id = ntohl (msg->id);
569
570   attr_len = ntohs (msg->attr_len);
571   LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing attribute result.\n");
572
573
574   for (it = h->it_head; NULL != it; it = it->next)
575     if (it->r_id == r_id)
576       break;
577   for (op = h->op_head; NULL != op; op = op->next)
578     if (op->r_id == r_id)
579       break;
580   if ((NULL == it) && (NULL == op))
581     return;
582
583   if ((0 ==
584        (memcmp (&msg->identity, &identity_dummy, sizeof (identity_dummy)))))
585   {
586     if ((NULL == it) && (NULL == op))
587     {
588       GNUNET_break (0);
589       force_reconnect (h);
590       return;
591     }
592     if (NULL != it)
593     {
594       if (NULL != it->finish_cb)
595         it->finish_cb (it->finish_cb_cls);
596       free_it (it);
597     }
598     if (NULL != op)
599     {
600       if (NULL != op->ar_cb)
601         op->ar_cb (op->cls, NULL, NULL);
602       GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
603       free_op (op);
604     }
605     return;
606   }
607
608   {
609     struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr;
610     attr = GNUNET_RECLAIM_ATTRIBUTE_deserialize ((char *) &msg[1], attr_len);
611     if (NULL != it)
612     {
613       if (NULL != it->proc)
614         it->proc (it->proc_cls, &msg->identity, attr);
615     }
616     else if (NULL != op)
617     {
618       if (NULL != op->ar_cb)
619         op->ar_cb (op->cls, &msg->identity, attr);
620     }
621     GNUNET_free (attr);
622     return;
623   }
624   GNUNET_assert (0);
625 }
626
627
628 /**
629  * Handle an incoming message of type
630  * #GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT
631  *
632  * @param cls
633  * @param msg the message we received
634  */
635 static void
636 handle_ticket_result (void *cls, const struct TicketResultMessage *msg)
637 {
638   struct GNUNET_RECLAIM_Handle *handle = cls;
639   struct GNUNET_RECLAIM_Operation *op;
640   struct GNUNET_RECLAIM_TicketIterator *it;
641   uint32_t r_id = ntohl (msg->id);
642   static const struct GNUNET_RECLAIM_Ticket ticket;
643   for (op = handle->op_head; NULL != op; op = op->next)
644     if (op->r_id == r_id)
645       break;
646   for (it = handle->ticket_it_head; NULL != it; it = it->next)
647     if (it->r_id == r_id)
648       break;
649   if ((NULL == op) && (NULL == it))
650     return;
651   if (NULL != op)
652   {
653     GNUNET_CONTAINER_DLL_remove (handle->op_head, handle->op_tail, op);
654     if (0 ==
655         memcmp (&msg->ticket, &ticket, sizeof (struct GNUNET_RECLAIM_Ticket)))
656     {
657       if (NULL != op->tr_cb)
658         op->tr_cb (op->cls, NULL);
659     }
660     else
661     {
662       if (NULL != op->tr_cb)
663         op->tr_cb (op->cls, &msg->ticket);
664     }
665     free_op (op);
666     return;
667   }
668   else if (NULL != it)
669   {
670     if (0 ==
671         memcmp (&msg->ticket, &ticket, sizeof (struct GNUNET_RECLAIM_Ticket)))
672     {
673       GNUNET_CONTAINER_DLL_remove (handle->ticket_it_head,
674                                    handle->ticket_it_tail,
675                                    it);
676       it->finish_cb (it->finish_cb_cls);
677       GNUNET_free (it);
678     }
679     else
680     {
681       if (NULL != it->tr_cb)
682         it->tr_cb (it->cls, &msg->ticket);
683     }
684     return;
685   }
686   GNUNET_break (0);
687 }
688
689
690 /**
691  * Handle an incoming message of type
692  * #GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT
693  *
694  * @param cls
695  * @param msg the message we received
696  */
697 static void
698 handle_revoke_ticket_result (void *cls,
699                              const struct RevokeTicketResultMessage *msg)
700 {
701   struct GNUNET_RECLAIM_Handle *h = cls;
702   struct GNUNET_RECLAIM_Operation *op;
703   uint32_t r_id = ntohl (msg->id);
704   int32_t success;
705
706   LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing revocation result.\n");
707
708
709   for (op = h->op_head; NULL != op; op = op->next)
710     if (op->r_id == r_id)
711       break;
712   if (NULL == op)
713     return;
714   success = ntohl (msg->success);
715   {
716     if (NULL != op->rvk_cb)
717     {
718       op->rvk_cb (op->cls, success, NULL);
719     }
720     GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
721     free_op (op);
722     return;
723   }
724   GNUNET_assert (0);
725 }
726
727
728 /**
729  * Try again to connect to the service.
730  *
731  * @param h handle to the reclaim service.
732  */
733 static void
734 reconnect (struct GNUNET_RECLAIM_Handle *h)
735 {
736   struct GNUNET_MQ_MessageHandler handlers[] =
737     {GNUNET_MQ_hd_fixed_size (success_response,
738                               GNUNET_MESSAGE_TYPE_RECLAIM_SUCCESS_RESPONSE,
739                               struct SuccessResultMessage,
740                               h),
741      GNUNET_MQ_hd_var_size (attribute_result,
742                             GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_RESULT,
743                             struct AttributeResultMessage,
744                             h),
745      GNUNET_MQ_hd_fixed_size (ticket_result,
746                               GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_RESULT,
747                               struct TicketResultMessage,
748                               h),
749      GNUNET_MQ_hd_var_size (consume_ticket_result,
750                             GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET_RESULT,
751                             struct ConsumeTicketResultMessage,
752                             h),
753      GNUNET_MQ_hd_fixed_size (revoke_ticket_result,
754                               GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET_RESULT,
755                               struct RevokeTicketResultMessage,
756                               h),
757      GNUNET_MQ_handler_end ()};
758   struct GNUNET_RECLAIM_Operation *op;
759
760   GNUNET_assert (NULL == h->mq);
761   LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting to reclaim service.\n");
762
763   h->mq =
764     GNUNET_CLIENT_connect (h->cfg, "reclaim", handlers, &mq_error_handler, h);
765   if (NULL == h->mq)
766     return;
767   for (op = h->op_head; NULL != op; op = op->next)
768     GNUNET_MQ_send_copy (h->mq, op->env);
769 }
770
771
772 /**
773  * Connect to the reclaim service.
774  *
775  * @param cfg the configuration to use
776  * @return handle to use
777  */
778 struct GNUNET_RECLAIM_Handle *
779 GNUNET_RECLAIM_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
780 {
781   struct GNUNET_RECLAIM_Handle *h;
782
783   h = GNUNET_new (struct GNUNET_RECLAIM_Handle);
784   h->cfg = cfg;
785   reconnect (h);
786   if (NULL == h->mq)
787   {
788     GNUNET_free (h);
789     return NULL;
790   }
791   return h;
792 }
793
794
795 /**
796  * Cancel an operation. Note that the operation MAY still
797  * be executed; this merely cancels the continuation; if the request
798  * was already transmitted, the service may still choose to complete
799  * the operation.
800  *
801  * @param op operation to cancel
802  */
803 void
804 GNUNET_RECLAIM_cancel (struct GNUNET_RECLAIM_Operation *op)
805 {
806   struct GNUNET_RECLAIM_Handle *h = op->h;
807
808   GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op);
809   free_op (op);
810 }
811
812
813 /**
814  * Disconnect from service
815  *
816  * @param h handle to destroy
817  */
818 void
819 GNUNET_RECLAIM_disconnect (struct GNUNET_RECLAIM_Handle *h)
820 {
821   GNUNET_assert (NULL != h);
822   if (NULL != h->mq)
823   {
824     GNUNET_MQ_destroy (h->mq);
825     h->mq = NULL;
826   }
827   if (NULL != h->reconnect_task)
828   {
829     GNUNET_SCHEDULER_cancel (h->reconnect_task);
830     h->reconnect_task = NULL;
831   }
832   GNUNET_assert (NULL == h->op_head);
833   GNUNET_free (h);
834 }
835
836 /**
837  * Store an attribute.  If the attribute is already present,
838  * it is replaced with the new attribute.
839  *
840  * @param h handle to the re:claimID service
841  * @param pkey private key of the identity
842  * @param attr the attribute value
843  * @param exp_interval the relative expiration interval for the attribute
844  * @param cont continuation to call when done
845  * @param cont_cls closure for @a cont
846  * @return handle to abort the request
847  */
848 struct GNUNET_RECLAIM_Operation *
849 GNUNET_RECLAIM_attribute_store (
850   struct GNUNET_RECLAIM_Handle *h,
851   const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
852   const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
853   const struct GNUNET_TIME_Relative *exp_interval,
854   GNUNET_RECLAIM_ContinuationWithStatus cont,
855   void *cont_cls)
856 {
857   struct GNUNET_RECLAIM_Operation *op;
858   struct AttributeStoreMessage *sam;
859   size_t attr_len;
860
861   op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
862   op->h = h;
863   op->as_cb = cont;
864   op->cls = cont_cls;
865   op->r_id = h->r_id_gen++;
866   GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
867   attr_len = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (attr);
868   op->env = GNUNET_MQ_msg_extra (sam,
869                                  attr_len,
870                                  GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_STORE);
871   sam->identity = *pkey;
872   sam->id = htonl (op->r_id);
873   sam->exp = GNUNET_htonll (exp_interval->rel_value_us);
874
875   GNUNET_RECLAIM_ATTRIBUTE_serialize (attr, (char *) &sam[1]);
876
877   sam->attr_len = htons (attr_len);
878   if (NULL != h->mq)
879     GNUNET_MQ_send_copy (h->mq, op->env);
880   return op;
881 }
882
883
884 /**
885  * Delete an attribute. Tickets used to share this attribute are updated
886  * accordingly.
887  *
888  * @param h handle to the re:claimID service
889  * @param pkey Private key of the identity to add an attribute to
890  * @param attr The attribute
891  * @param cont Continuation to call when done
892  * @param cont_cls Closure for @a cont
893  * @return handle Used to to abort the request
894  */
895 struct GNUNET_RECLAIM_Operation *
896 GNUNET_RECLAIM_attribute_delete (
897   struct GNUNET_RECLAIM_Handle *h,
898   const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey,
899   const struct GNUNET_RECLAIM_ATTRIBUTE_Claim *attr,
900   GNUNET_RECLAIM_ContinuationWithStatus cont,
901   void *cont_cls)
902 {
903   struct GNUNET_RECLAIM_Operation *op;
904   struct AttributeDeleteMessage *dam;
905   size_t attr_len;
906
907   op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
908   op->h = h;
909   op->as_cb = cont;
910   op->cls = cont_cls;
911   op->r_id = h->r_id_gen++;
912   GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
913   attr_len = GNUNET_RECLAIM_ATTRIBUTE_serialize_get_size (attr);
914   op->env = GNUNET_MQ_msg_extra (dam,
915                                  attr_len,
916                                  GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_DELETE);
917   dam->identity = *pkey;
918   dam->id = htonl (op->r_id);
919   GNUNET_RECLAIM_ATTRIBUTE_serialize (attr, (char *) &dam[1]);
920
921   dam->attr_len = htons (attr_len);
922   if (NULL != h->mq)
923     GNUNET_MQ_send_copy (h->mq, op->env);
924   return op;
925 }
926
927
928 /**
929  * List all attributes for a local identity.
930  * This MUST lock the `struct GNUNET_RECLAIM_Handle`
931  * for any other calls than #GNUNET_RECLAIM_get_attributes_next() and
932  * #GNUNET_RECLAIM_get_attributes_stop. @a proc will be called once
933  * immediately, and then again after
934  * #GNUNET_RECLAIM_get_attributes_next() is invoked.
935  *
936  * On error (disconnect), @a error_cb will be invoked.
937  * On normal completion, @a finish_cb proc will be
938  * invoked.
939  *
940  * @param h Handle to the re:claimID service
941  * @param identity Identity to iterate over
942  * @param error_cb Function to call on error (i.e. disconnect),
943  *        the handle is afterwards invalid
944  * @param error_cb_cls Closure for @a error_cb
945  * @param proc Function to call on each attribute
946  * @param proc_cls Closure for @a proc
947  * @param finish_cb Function to call on completion
948  *        the handle is afterwards invalid
949  * @param finish_cb_cls Closure for @a finish_cb
950  * @return an iterator Handle to use for iteration
951  */
952 struct GNUNET_RECLAIM_AttributeIterator *
953 GNUNET_RECLAIM_get_attributes_start (
954   struct GNUNET_RECLAIM_Handle *h,
955   const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
956   GNUNET_SCHEDULER_TaskCallback error_cb,
957   void *error_cb_cls,
958   GNUNET_RECLAIM_AttributeResult proc,
959   void *proc_cls,
960   GNUNET_SCHEDULER_TaskCallback finish_cb,
961   void *finish_cb_cls)
962 {
963   struct GNUNET_RECLAIM_AttributeIterator *it;
964   struct GNUNET_MQ_Envelope *env;
965   struct AttributeIterationStartMessage *msg;
966   uint32_t rid;
967
968   rid = h->r_id_gen++;
969   it = GNUNET_new (struct GNUNET_RECLAIM_AttributeIterator);
970   it->h = h;
971   it->error_cb = error_cb;
972   it->error_cb_cls = error_cb_cls;
973   it->finish_cb = finish_cb;
974   it->finish_cb_cls = finish_cb_cls;
975   it->proc = proc;
976   it->proc_cls = proc_cls;
977   it->r_id = rid;
978   it->identity = *identity;
979   GNUNET_CONTAINER_DLL_insert_tail (h->it_head, h->it_tail, it);
980   env =
981     GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_START);
982   msg->id = htonl (rid);
983   msg->identity = *identity;
984   if (NULL == h->mq)
985     it->env = env;
986   else
987     GNUNET_MQ_send (h->mq, env);
988   return it;
989 }
990
991
992 /**
993  * Calls the record processor specified in #GNUNET_RECLAIM_get_attributes_start
994  * for the next record.
995  *
996  * @param it the iterator
997  */
998 void
999 GNUNET_RECLAIM_get_attributes_next (struct GNUNET_RECLAIM_AttributeIterator *it)
1000 {
1001   struct GNUNET_RECLAIM_Handle *h = it->h;
1002   struct AttributeIterationNextMessage *msg;
1003   struct GNUNET_MQ_Envelope *env;
1004
1005   env =
1006     GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_NEXT);
1007   msg->id = htonl (it->r_id);
1008   GNUNET_MQ_send (h->mq, env);
1009 }
1010
1011
1012 /**
1013  * Stops iteration and releases the handle for further calls. Must
1014  * be called on any iteration that has not yet completed prior to calling
1015  * #GNUNET_RECLAIM_disconnect.
1016  *
1017  * @param it the iterator
1018  */
1019 void
1020 GNUNET_RECLAIM_get_attributes_stop (struct GNUNET_RECLAIM_AttributeIterator *it)
1021 {
1022   struct GNUNET_RECLAIM_Handle *h = it->h;
1023   struct GNUNET_MQ_Envelope *env;
1024   struct AttributeIterationStopMessage *msg;
1025
1026   if (NULL != h->mq)
1027   {
1028     env =
1029       GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_ATTRIBUTE_ITERATION_STOP);
1030     msg->id = htonl (it->r_id);
1031     GNUNET_MQ_send (h->mq, env);
1032   }
1033   free_it (it);
1034 }
1035
1036
1037 /**
1038  * Issues a ticket to another relying party. The identity may use
1039  * @GNUNET_RECLAIM_ticket_consume to consume the ticket
1040  * and retrieve the attributes specified in the attribute list.
1041  *
1042  * @param h the reclaim to use
1043  * @param iss the issuing identity (= the user)
1044  * @param rp the subject of the ticket (= the relying party)
1045  * @param attrs the attributes that the relying party is given access to
1046  * @param cb the callback
1047  * @param cb_cls the callback closure
1048  * @return handle to abort the operation
1049  */
1050 struct GNUNET_RECLAIM_Operation *
1051 GNUNET_RECLAIM_ticket_issue (
1052   struct GNUNET_RECLAIM_Handle *h,
1053   const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss,
1054   const struct GNUNET_CRYPTO_EcdsaPublicKey *rp,
1055   const struct GNUNET_RECLAIM_ATTRIBUTE_ClaimList *attrs,
1056   GNUNET_RECLAIM_TicketCallback cb,
1057   void *cb_cls)
1058 {
1059   struct GNUNET_RECLAIM_Operation *op;
1060   struct IssueTicketMessage *tim;
1061   size_t attr_len;
1062   fprintf (stderr, "Issuing ticket\n");
1063   op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1064   op->h = h;
1065   op->tr_cb = cb;
1066   op->cls = cb_cls;
1067   op->r_id = h->r_id_gen++;
1068   GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1069   attr_len = GNUNET_RECLAIM_ATTRIBUTE_list_serialize_get_size (attrs);
1070   op->env = GNUNET_MQ_msg_extra (tim,
1071                                  attr_len,
1072                                  GNUNET_MESSAGE_TYPE_RECLAIM_ISSUE_TICKET);
1073   tim->identity = *iss;
1074   tim->rp = *rp;
1075   tim->id = htonl (op->r_id);
1076
1077   GNUNET_RECLAIM_ATTRIBUTE_list_serialize (attrs, (char *) &tim[1]);
1078
1079   tim->attr_len = htons (attr_len);
1080   if (NULL != h->mq)
1081     GNUNET_MQ_send_copy (h->mq, op->env);
1082   return op;
1083 }
1084
1085
1086 /**
1087  * Consumes an issued ticket. The ticket is persisted
1088  * and used to retrieve identity information from the issuer
1089  *
1090  * @param h the reclaim to use
1091  * @param identity the identity that is the subject of the issued ticket (the
1092  * relying party)
1093  * @param ticket the issued ticket to consume
1094  * @param cb the callback to call
1095  * @param cb_cls the callback closure
1096  * @return handle to abort the operation
1097  */
1098 struct GNUNET_RECLAIM_Operation *
1099 GNUNET_RECLAIM_ticket_consume (
1100   struct GNUNET_RECLAIM_Handle *h,
1101   const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
1102   const struct GNUNET_RECLAIM_Ticket *ticket,
1103   GNUNET_RECLAIM_AttributeResult cb,
1104   void *cb_cls)
1105 {
1106   struct GNUNET_RECLAIM_Operation *op;
1107   struct ConsumeTicketMessage *ctm;
1108
1109   op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1110   op->h = h;
1111   op->ar_cb = cb;
1112   op->cls = cb_cls;
1113   op->r_id = h->r_id_gen++;
1114   GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1115   op->env = GNUNET_MQ_msg (ctm, GNUNET_MESSAGE_TYPE_RECLAIM_CONSUME_TICKET);
1116   ctm->identity = *identity;
1117   ctm->id = htonl (op->r_id);
1118   ctm->ticket = *ticket;
1119   if (NULL != h->mq)
1120     GNUNET_MQ_send_copy (h->mq, op->env);
1121   return op;
1122 }
1123
1124
1125 /**
1126  * Lists all tickets that have been issued to remote
1127  * identites (relying parties)
1128  *
1129  * @param h the reclaim to use
1130  * @param identity the issuing identity
1131  * @param error_cb function to call on error (i.e. disconnect),
1132  *        the handle is afterwards invalid
1133  * @param error_cb_cls closure for @a error_cb
1134  * @param proc function to call on each ticket; it
1135  *        will be called repeatedly with a value (if available)
1136  * @param proc_cls closure for @a proc
1137  * @param finish_cb function to call on completion
1138  *        the handle is afterwards invalid
1139  * @param finish_cb_cls closure for @a finish_cb
1140  * @return an iterator handle to use for iteration
1141  */
1142 struct GNUNET_RECLAIM_TicketIterator *
1143 GNUNET_RECLAIM_ticket_iteration_start (
1144   struct GNUNET_RECLAIM_Handle *h,
1145   const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
1146   GNUNET_SCHEDULER_TaskCallback error_cb,
1147   void *error_cb_cls,
1148   GNUNET_RECLAIM_TicketCallback proc,
1149   void *proc_cls,
1150   GNUNET_SCHEDULER_TaskCallback finish_cb,
1151   void *finish_cb_cls)
1152 {
1153   struct GNUNET_RECLAIM_TicketIterator *it;
1154   struct GNUNET_MQ_Envelope *env;
1155   struct TicketIterationStartMessage *msg;
1156   uint32_t rid;
1157
1158   rid = h->r_id_gen++;
1159   it = GNUNET_new (struct GNUNET_RECLAIM_TicketIterator);
1160   it->h = h;
1161   it->error_cb = error_cb;
1162   it->error_cb_cls = error_cb_cls;
1163   it->finish_cb = finish_cb;
1164   it->finish_cb_cls = finish_cb_cls;
1165   it->tr_cb = proc;
1166   it->cls = proc_cls;
1167   it->r_id = rid;
1168   GNUNET_CONTAINER_DLL_insert_tail (h->ticket_it_head, h->ticket_it_tail, it);
1169   env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_START);
1170   msg->id = htonl (rid);
1171   msg->identity = *identity;
1172   if (NULL == h->mq)
1173     it->env = env;
1174   else
1175     GNUNET_MQ_send (h->mq, env);
1176   return it;
1177 }
1178
1179
1180 /**
1181  * Calls the ticket processor specified in
1182  * #GNUNET_RECLAIM_ticket_iteration_start for the next record.
1183  *
1184  * @param it the iterator
1185  */
1186 void
1187 GNUNET_RECLAIM_ticket_iteration_next (struct GNUNET_RECLAIM_TicketIterator *it)
1188 {
1189   struct GNUNET_RECLAIM_Handle *h = it->h;
1190   struct TicketIterationNextMessage *msg;
1191   struct GNUNET_MQ_Envelope *env;
1192
1193   env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_NEXT);
1194   msg->id = htonl (it->r_id);
1195   GNUNET_MQ_send (h->mq, env);
1196 }
1197
1198
1199 /**
1200  * Stops iteration and releases the handle for further calls.  Must
1201  * be called on any iteration that has not yet completed prior to calling
1202  * #GNUNET_RECLAIM_disconnect.
1203  *
1204  * @param it the iterator
1205  */
1206 void
1207 GNUNET_RECLAIM_ticket_iteration_stop (struct GNUNET_RECLAIM_TicketIterator *it)
1208 {
1209   struct GNUNET_RECLAIM_Handle *h = it->h;
1210   struct GNUNET_MQ_Envelope *env;
1211   struct TicketIterationStopMessage *msg;
1212
1213   if (NULL != h->mq)
1214   {
1215     env =
1216       GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_TICKET_ITERATION_STOP);
1217     msg->id = htonl (it->r_id);
1218     GNUNET_MQ_send (h->mq, env);
1219   }
1220   GNUNET_free (it);
1221 }
1222
1223
1224 /**
1225  * Revoked an issued ticket. The relying party will be unable to retrieve
1226  * attributes. Other issued tickets remain unaffected.
1227  * This includes tickets issued to other relying parties as well as to
1228  * other tickets issued to the audience specified in this ticket.
1229  *
1230  * @param h the identity provider to use
1231  * @param identity the issuing identity
1232  * @param ticket the ticket to revoke
1233  * @param cb the callback
1234  * @param cb_cls the callback closure
1235  * @return handle to abort the operation
1236  */
1237 struct GNUNET_RECLAIM_Operation *
1238 GNUNET_RECLAIM_ticket_revoke (
1239   struct GNUNET_RECLAIM_Handle *h,
1240   const struct GNUNET_CRYPTO_EcdsaPrivateKey *identity,
1241   const struct GNUNET_RECLAIM_Ticket *ticket,
1242   GNUNET_RECLAIM_ContinuationWithStatus cb,
1243   void *cb_cls)
1244 {
1245   struct GNUNET_RECLAIM_Operation *op;
1246   struct RevokeTicketMessage *msg;
1247   uint32_t rid;
1248
1249   rid = h->r_id_gen++;
1250   op = GNUNET_new (struct GNUNET_RECLAIM_Operation);
1251   op->h = h;
1252   op->rvk_cb = cb;
1253   op->cls = cb_cls;
1254   op->r_id = rid;
1255   GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op);
1256   op->env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RECLAIM_REVOKE_TICKET);
1257   msg->id = htonl (rid);
1258   msg->identity = *identity;
1259   msg->ticket = *ticket;
1260   if (NULL != h->mq)
1261   {
1262     GNUNET_MQ_send (h->mq, op->env);
1263     op->env = NULL;
1264   }
1265   return op;
1266 }
1267
1268
1269 /* end of reclaim_api.c */