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