diff options
Diffstat (limited to 'src/reclaim/gnunet-service-reclaim_tickets.c')
-rw-r--r-- | src/reclaim/gnunet-service-reclaim_tickets.c | 1853 |
1 files changed, 0 insertions, 1853 deletions
diff --git a/src/reclaim/gnunet-service-reclaim_tickets.c b/src/reclaim/gnunet-service-reclaim_tickets.c deleted file mode 100644 index 5d3119c6f..000000000 --- a/src/reclaim/gnunet-service-reclaim_tickets.c +++ /dev/null | |||
@@ -1,1853 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2012-2015 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @author Martin Schanzenbach | ||
23 | * @file src/reclaim/gnunet-service-reclaim_tickets.c | ||
24 | * @brief reclaim tickets | ||
25 | * | ||
26 | */ | ||
27 | #include <inttypes.h> | ||
28 | #include "gnunet-service-reclaim_tickets.h" | ||
29 | |||
30 | |||
31 | /** | ||
32 | * FIXME: the default ticket iteration interval should probably | ||
33 | * be the minimim attribute expiration. | ||
34 | */ | ||
35 | #define DEFAULT_TICKET_REFRESH_INTERVAL GNUNET_TIME_UNIT_HOURS | ||
36 | |||
37 | /** | ||
38 | * Handle for a parallel GNS lookup job | ||
39 | * (Declaration further below) | ||
40 | */ | ||
41 | struct ParallelLookup; | ||
42 | |||
43 | |||
44 | /** | ||
45 | * A reference to a ticket stored in GNS | ||
46 | */ | ||
47 | struct TicketReference | ||
48 | { | ||
49 | /** | ||
50 | * DLL | ||
51 | */ | ||
52 | struct TicketReference *next; | ||
53 | |||
54 | /** | ||
55 | * DLL | ||
56 | */ | ||
57 | struct TicketReference *prev; | ||
58 | |||
59 | /** | ||
60 | * Attributes | ||
61 | */ | ||
62 | struct GNUNET_RECLAIM_AttributeList *attrs; | ||
63 | |||
64 | /** | ||
65 | * Tickets | ||
66 | */ | ||
67 | struct GNUNET_RECLAIM_Ticket ticket; | ||
68 | }; | ||
69 | |||
70 | |||
71 | /** | ||
72 | * Handle to a consume operation | ||
73 | */ | ||
74 | struct RECLAIM_TICKETS_ConsumeHandle | ||
75 | { | ||
76 | /** | ||
77 | * Ticket | ||
78 | */ | ||
79 | struct GNUNET_RECLAIM_Ticket ticket; | ||
80 | |||
81 | /** | ||
82 | * LookupRequest | ||
83 | */ | ||
84 | struct GNUNET_GNS_LookupRequest *lookup_request; | ||
85 | |||
86 | /** | ||
87 | * Audience Key | ||
88 | */ | ||
89 | struct GNUNET_IDENTITY_PrivateKey identity; | ||
90 | |||
91 | /** | ||
92 | * Audience Key | ||
93 | */ | ||
94 | struct GNUNET_IDENTITY_PublicKey identity_pub; | ||
95 | |||
96 | /** | ||
97 | * Lookup DLL | ||
98 | */ | ||
99 | struct ParallelLookup *parallel_lookups_head; | ||
100 | |||
101 | /** | ||
102 | * Lookup DLL | ||
103 | */ | ||
104 | struct ParallelLookup *parallel_lookups_tail; | ||
105 | |||
106 | /** | ||
107 | * Kill task | ||
108 | */ | ||
109 | struct GNUNET_SCHEDULER_Task *kill_task; | ||
110 | |||
111 | /** | ||
112 | * Attributes | ||
113 | */ | ||
114 | struct GNUNET_RECLAIM_AttributeList *attrs; | ||
115 | |||
116 | /** | ||
117 | * Presentations | ||
118 | */ | ||
119 | struct GNUNET_RECLAIM_PresentationList *presentations; | ||
120 | |||
121 | /** | ||
122 | * Lookup time | ||
123 | */ | ||
124 | struct GNUNET_TIME_Absolute lookup_start_time; | ||
125 | |||
126 | /** | ||
127 | * Callback | ||
128 | */ | ||
129 | RECLAIM_TICKETS_ConsumeCallback cb; | ||
130 | |||
131 | /** | ||
132 | * Callback closure | ||
133 | */ | ||
134 | void *cb_cls; | ||
135 | }; | ||
136 | |||
137 | |||
138 | /** | ||
139 | * Handle for a parallel GNS lookup job | ||
140 | */ | ||
141 | struct ParallelLookup | ||
142 | { | ||
143 | /* DLL */ | ||
144 | struct ParallelLookup *next; | ||
145 | |||
146 | /* DLL */ | ||
147 | struct ParallelLookup *prev; | ||
148 | |||
149 | /* The GNS request */ | ||
150 | struct GNUNET_GNS_LookupRequest *lookup_request; | ||
151 | |||
152 | /* The handle the return to */ | ||
153 | struct RECLAIM_TICKETS_ConsumeHandle *handle; | ||
154 | |||
155 | /** | ||
156 | * Lookup time | ||
157 | */ | ||
158 | struct GNUNET_TIME_Absolute lookup_start_time; | ||
159 | |||
160 | /* The label to look up */ | ||
161 | char *label; | ||
162 | }; | ||
163 | |||
164 | |||
165 | /** | ||
166 | * Ticket issue request handle | ||
167 | */ | ||
168 | struct TicketIssueHandle | ||
169 | { | ||
170 | /** | ||
171 | * Attributes to issue | ||
172 | */ | ||
173 | struct GNUNET_RECLAIM_AttributeList *attrs; | ||
174 | |||
175 | /** | ||
176 | * Presentations to add | ||
177 | */ | ||
178 | struct GNUNET_RECLAIM_PresentationList *presentations; | ||
179 | |||
180 | /** | ||
181 | * Issuer Key | ||
182 | */ | ||
183 | struct GNUNET_IDENTITY_PrivateKey identity; | ||
184 | |||
185 | /** | ||
186 | * Ticket to issue | ||
187 | */ | ||
188 | struct GNUNET_RECLAIM_Ticket ticket; | ||
189 | |||
190 | /** | ||
191 | * QueueEntry | ||
192 | */ | ||
193 | struct GNUNET_NAMESTORE_QueueEntry *ns_qe; | ||
194 | |||
195 | /** | ||
196 | * Namestore Iterator | ||
197 | */ | ||
198 | struct GNUNET_NAMESTORE_ZoneIterator *ns_it; | ||
199 | |||
200 | /** | ||
201 | * Callback | ||
202 | */ | ||
203 | RECLAIM_TICKETS_TicketResult cb; | ||
204 | |||
205 | /** | ||
206 | * Callback cls | ||
207 | */ | ||
208 | void *cb_cls; | ||
209 | }; | ||
210 | |||
211 | |||
212 | /** | ||
213 | * Ticket iterator | ||
214 | */ | ||
215 | struct RECLAIM_TICKETS_Iterator | ||
216 | { | ||
217 | /** | ||
218 | * Namestore queue entry | ||
219 | */ | ||
220 | struct GNUNET_NAMESTORE_ZoneIterator *ns_it; | ||
221 | |||
222 | /** | ||
223 | * Iter callback | ||
224 | */ | ||
225 | RECLAIM_TICKETS_TicketIter cb; | ||
226 | |||
227 | /** | ||
228 | * Iter cls | ||
229 | */ | ||
230 | void *cb_cls; | ||
231 | }; | ||
232 | |||
233 | |||
234 | struct RevokedAttributeEntry | ||
235 | { | ||
236 | /** | ||
237 | * DLL | ||
238 | */ | ||
239 | struct RevokedAttributeEntry *next; | ||
240 | |||
241 | /** | ||
242 | * DLL | ||
243 | */ | ||
244 | struct RevokedAttributeEntry *prev; | ||
245 | |||
246 | /** | ||
247 | * Old ID of the attribute | ||
248 | */ | ||
249 | struct GNUNET_RECLAIM_Identifier old_id; | ||
250 | |||
251 | /** | ||
252 | * New ID of the attribute | ||
253 | */ | ||
254 | struct GNUNET_RECLAIM_Identifier new_id; | ||
255 | }; | ||
256 | |||
257 | |||
258 | /** | ||
259 | * Ticket revocation request handle | ||
260 | */ | ||
261 | struct RECLAIM_TICKETS_RevokeHandle | ||
262 | { | ||
263 | /** | ||
264 | * Issuer Key | ||
265 | */ | ||
266 | struct GNUNET_IDENTITY_PrivateKey identity; | ||
267 | |||
268 | /** | ||
269 | * Callback | ||
270 | */ | ||
271 | RECLAIM_TICKETS_RevokeCallback cb; | ||
272 | |||
273 | /** | ||
274 | * Callback cls | ||
275 | */ | ||
276 | void *cb_cls; | ||
277 | |||
278 | /** | ||
279 | * Ticket to issue | ||
280 | */ | ||
281 | struct GNUNET_RECLAIM_Ticket ticket; | ||
282 | |||
283 | /** | ||
284 | * QueueEntry | ||
285 | */ | ||
286 | struct GNUNET_NAMESTORE_QueueEntry *ns_qe; | ||
287 | |||
288 | /** | ||
289 | * Namestore iterator | ||
290 | */ | ||
291 | struct GNUNET_NAMESTORE_ZoneIterator *ns_it; | ||
292 | |||
293 | /** | ||
294 | * Revoked attributes | ||
295 | */ | ||
296 | struct RevokedAttributeEntry *attrs_head; | ||
297 | |||
298 | /** | ||
299 | * Revoked attributes | ||
300 | */ | ||
301 | struct RevokedAttributeEntry *attrs_tail; | ||
302 | |||
303 | /** | ||
304 | * Current attribute to move | ||
305 | */ | ||
306 | struct RevokedAttributeEntry *move_attr; | ||
307 | |||
308 | /** | ||
309 | * Number of attributes in ticket | ||
310 | */ | ||
311 | unsigned int ticket_attrs; | ||
312 | |||
313 | /** | ||
314 | * Tickets to update | ||
315 | */ | ||
316 | struct TicketRecordsEntry *tickets_to_update_head; | ||
317 | |||
318 | /** | ||
319 | * Tickets to update | ||
320 | */ | ||
321 | struct TicketRecordsEntry *tickets_to_update_tail; | ||
322 | }; | ||
323 | |||
324 | |||
325 | /** | ||
326 | * Ticket expiration interval | ||
327 | */ | ||
328 | static struct GNUNET_TIME_Relative ticket_refresh_interval; | ||
329 | |||
330 | |||
331 | /* Namestore handle */ | ||
332 | static struct GNUNET_NAMESTORE_Handle *nsh; | ||
333 | |||
334 | |||
335 | /* GNS handle */ | ||
336 | static struct GNUNET_GNS_Handle *gns; | ||
337 | |||
338 | |||
339 | /* Handle to the statistics service */ | ||
340 | static struct GNUNET_STATISTICS_Handle *stats; | ||
341 | |||
342 | |||
343 | /** | ||
344 | * Cleanup revoke handle | ||
345 | * | ||
346 | * @param rh the ticket revocation handle | ||
347 | */ | ||
348 | static void | ||
349 | cleanup_rvk (struct RECLAIM_TICKETS_RevokeHandle *rh) | ||
350 | { | ||
351 | struct RevokedAttributeEntry *ae; | ||
352 | struct TicketRecordsEntry *le; | ||
353 | |||
354 | if (NULL != rh->ns_qe) | ||
355 | GNUNET_NAMESTORE_cancel (rh->ns_qe); | ||
356 | if (NULL != rh->ns_it) | ||
357 | GNUNET_NAMESTORE_zone_iteration_stop (rh->ns_it); | ||
358 | while (NULL != (ae = rh->attrs_head)) | ||
359 | { | ||
360 | GNUNET_CONTAINER_DLL_remove (rh->attrs_head, rh->attrs_tail, ae); | ||
361 | GNUNET_free (ae); | ||
362 | } | ||
363 | while (NULL != (le = rh->tickets_to_update_head)) | ||
364 | { | ||
365 | GNUNET_CONTAINER_DLL_remove (rh->tickets_to_update_head, | ||
366 | rh->tickets_to_update_head, | ||
367 | le); | ||
368 | if (NULL != le->data) | ||
369 | GNUNET_free (le->data); | ||
370 | if (NULL != le->label) | ||
371 | GNUNET_free (le->label); | ||
372 | GNUNET_free (le); | ||
373 | } | ||
374 | GNUNET_free (rh); | ||
375 | } | ||
376 | |||
377 | |||
378 | /** | ||
379 | * For each ticket, store new, updated attribute references | ||
380 | * (Implementation further below) | ||
381 | * | ||
382 | * @param cls handle to the operation | ||
383 | */ | ||
384 | static void | ||
385 | process_tickets (void *cls); | ||
386 | |||
387 | |||
388 | /** | ||
389 | * Finished storing updated attribute references. | ||
390 | * Abort on error, else continue processing tickets | ||
391 | * | ||
392 | * @param cls handle to the operation | ||
393 | * @param success result of namestore operation | ||
394 | * @param emsg (NULL on success) | ||
395 | */ | ||
396 | static void | ||
397 | ticket_processed (void *cls, int32_t success, const char *emsg) | ||
398 | { | ||
399 | struct RECLAIM_TICKETS_RevokeHandle *rvk = cls; | ||
400 | |||
401 | rvk->ns_qe = NULL; | ||
402 | GNUNET_SCHEDULER_add_now (&process_tickets, rvk); | ||
403 | } | ||
404 | |||
405 | |||
406 | /** | ||
407 | * For each ticket, store new, updated attribute references | ||
408 | * | ||
409 | * @param cls handle to the operation | ||
410 | */ | ||
411 | static void | ||
412 | process_tickets (void *cls) | ||
413 | { | ||
414 | struct RECLAIM_TICKETS_RevokeHandle *rvk = cls; | ||
415 | struct TicketRecordsEntry *le; | ||
416 | struct RevokedAttributeEntry *ae; | ||
417 | |||
418 | if (NULL == rvk->tickets_to_update_head) | ||
419 | { | ||
420 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
421 | "Finished updatding tickets, success\n"); | ||
422 | rvk->cb (rvk->cb_cls, GNUNET_OK); | ||
423 | cleanup_rvk (rvk); | ||
424 | return; | ||
425 | } | ||
426 | le = rvk->tickets_to_update_head; | ||
427 | GNUNET_CONTAINER_DLL_remove (rvk->tickets_to_update_head, | ||
428 | rvk->tickets_to_update_tail, | ||
429 | le); | ||
430 | struct GNUNET_GNSRECORD_Data rd[le->rd_count]; | ||
431 | if (GNUNET_OK != GNUNET_GNSRECORD_records_deserialize (le->data_size, | ||
432 | le->data, | ||
433 | le->rd_count, | ||
434 | rd)) | ||
435 | { | ||
436 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
437 | "Unable to deserialize ticket record(s)\n"); | ||
438 | rvk->cb (rvk->cb_cls, GNUNET_SYSERR); | ||
439 | cleanup_rvk (rvk); | ||
440 | return; | ||
441 | } | ||
442 | for (int i = 0; i < le->rd_count; i++) | ||
443 | { | ||
444 | if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF != rd[i].record_type) | ||
445 | continue; | ||
446 | for (ae = rvk->attrs_head; NULL != ae; ae = ae->next) | ||
447 | { | ||
448 | if (0 != memcmp (rd[i].data, &ae->old_id, sizeof(ae->old_id))) | ||
449 | continue; | ||
450 | rd[i].data = &ae->new_id; | ||
451 | } | ||
452 | } | ||
453 | rvk->ns_qe = GNUNET_NAMESTORE_records_store (nsh, | ||
454 | &rvk->identity, | ||
455 | le->label, | ||
456 | le->rd_count, | ||
457 | rd, | ||
458 | &ticket_processed, | ||
459 | rvk); | ||
460 | GNUNET_free (le->label); | ||
461 | GNUNET_free (le->data); | ||
462 | GNUNET_free (le); | ||
463 | } | ||
464 | |||
465 | |||
466 | /** | ||
467 | * Done collecting tickets. Start processing. | ||
468 | * | ||
469 | * @param cls handle to the operation | ||
470 | */ | ||
471 | static void | ||
472 | rvk_ticket_update_finished (void *cls) | ||
473 | { | ||
474 | struct RECLAIM_TICKETS_RevokeHandle *rvk = cls; | ||
475 | |||
476 | rvk->ns_it = NULL; | ||
477 | GNUNET_SCHEDULER_add_now (&process_tickets, rvk); | ||
478 | } | ||
479 | |||
480 | |||
481 | /** | ||
482 | * We need to update all other tickets with the new attribute IDs. | ||
483 | * We first collect them all. Processing after. | ||
484 | * | ||
485 | * @param cls handle to the operation | ||
486 | * @param zone ticket issuer private key | ||
487 | * @param label ticket rnd | ||
488 | * @param rd_cound size of record set | ||
489 | * @param rd record set | ||
490 | */ | ||
491 | static void | ||
492 | rvk_ticket_update (void *cls, | ||
493 | const struct GNUNET_IDENTITY_PrivateKey *zone, | ||
494 | const char *label, | ||
495 | unsigned int rd_count, | ||
496 | const struct GNUNET_GNSRECORD_Data *rd) | ||
497 | { | ||
498 | struct RECLAIM_TICKETS_RevokeHandle *rvk = cls; | ||
499 | struct TicketRecordsEntry *le; | ||
500 | struct RevokedAttributeEntry *ae; | ||
501 | int has_changed = GNUNET_NO; | ||
502 | |||
503 | /** Let everything point to the old record **/ | ||
504 | for (int i = 0; i < rd_count; i++) | ||
505 | { | ||
506 | if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF != rd[i].record_type) | ||
507 | continue; | ||
508 | for (ae = rvk->attrs_head; NULL != ae; ae = ae->next) | ||
509 | { | ||
510 | if (0 != memcmp (rd[i].data, &ae->old_id, sizeof(ae->old_id))) | ||
511 | continue; | ||
512 | has_changed = GNUNET_YES; | ||
513 | break; | ||
514 | } | ||
515 | if (GNUNET_YES == has_changed) | ||
516 | break; | ||
517 | } | ||
518 | if (GNUNET_YES == has_changed) | ||
519 | { | ||
520 | le = GNUNET_new (struct TicketRecordsEntry); | ||
521 | le->data_size = GNUNET_GNSRECORD_records_get_size (rd_count, rd); | ||
522 | le->data = GNUNET_malloc (le->data_size); | ||
523 | le->rd_count = rd_count; | ||
524 | le->label = GNUNET_strdup (label); | ||
525 | GNUNET_GNSRECORD_records_serialize (rd_count, rd, le->data_size, le->data); | ||
526 | GNUNET_CONTAINER_DLL_insert (rvk->tickets_to_update_head, | ||
527 | rvk->tickets_to_update_tail, | ||
528 | le); | ||
529 | } | ||
530 | GNUNET_NAMESTORE_zone_iterator_next (rvk->ns_it, 1); | ||
531 | } | ||
532 | |||
533 | |||
534 | /** | ||
535 | * Error iterating namestore. Abort. | ||
536 | * | ||
537 | * @param cls handle to the operation | ||
538 | */ | ||
539 | static void | ||
540 | rvk_ns_iter_err (void *cls) | ||
541 | { | ||
542 | struct RECLAIM_TICKETS_RevokeHandle *rvk = cls; | ||
543 | |||
544 | rvk->ns_it = NULL; | ||
545 | rvk->cb (rvk->cb_cls, GNUNET_SYSERR); | ||
546 | cleanup_rvk (rvk); | ||
547 | } | ||
548 | |||
549 | |||
550 | /** | ||
551 | * Error storing new attribute in namestore. Abort | ||
552 | * | ||
553 | * @param cls handle to the operation | ||
554 | */ | ||
555 | static void | ||
556 | rvk_ns_err (void *cls) | ||
557 | { | ||
558 | struct RECLAIM_TICKETS_RevokeHandle *rvk = cls; | ||
559 | |||
560 | rvk->ns_qe = NULL; | ||
561 | rvk->cb (rvk->cb_cls, GNUNET_SYSERR); | ||
562 | cleanup_rvk (rvk); | ||
563 | } | ||
564 | |||
565 | |||
566 | /** | ||
567 | * We change every attribute ID of the ticket attributes we | ||
568 | * want to revoke. | ||
569 | * When we are done, we need to update any other ticket which | ||
570 | * included references to any of the changed attributes. | ||
571 | * (Implementation further below) | ||
572 | * | ||
573 | * @param rvk handle to the operation | ||
574 | */ | ||
575 | static void | ||
576 | move_attrs (struct RECLAIM_TICKETS_RevokeHandle *rh); | ||
577 | |||
578 | |||
579 | /** | ||
580 | * Delayed continuation for move_attrs | ||
581 | * | ||
582 | * @param cls handle to the operation. | ||
583 | */ | ||
584 | static void | ||
585 | move_attrs_cont (void *cls) | ||
586 | { | ||
587 | move_attrs ((struct RECLAIM_TICKETS_RevokeHandle *) cls); | ||
588 | } | ||
589 | |||
590 | |||
591 | /** | ||
592 | * Done deleting the old record. Abort on error. | ||
593 | * Else, continue updating attribute IDs. | ||
594 | * | ||
595 | * @param cls handle to the operation | ||
596 | * @param success result of the namestore operation | ||
597 | * @param emsg error message (NULL on success) | ||
598 | */ | ||
599 | static void | ||
600 | del_attr_finished (void *cls, int32_t success, const char *emsg) | ||
601 | { | ||
602 | struct RECLAIM_TICKETS_RevokeHandle *rvk = cls; | ||
603 | |||
604 | rvk->ns_qe = NULL; | ||
605 | if (GNUNET_SYSERR == success) | ||
606 | { | ||
607 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
608 | "Error removing attribute: %s\n", | ||
609 | emsg); | ||
610 | rvk->cb (rvk->cb_cls, GNUNET_SYSERR); | ||
611 | cleanup_rvk (rvk); | ||
612 | return; | ||
613 | } | ||
614 | rvk->move_attr = rvk->move_attr->next; | ||
615 | GNUNET_SCHEDULER_add_now (&move_attrs_cont, rvk); | ||
616 | } | ||
617 | |||
618 | |||
619 | /** | ||
620 | * Updated an attribute ID. | ||
621 | * Abort on error if namestore operation failed. | ||
622 | * Else, we have to delete the old record. | ||
623 | * | ||
624 | * @param cls handle to the operation | ||
625 | * @param success result of the store operation | ||
626 | * @param emsg error message (NULL on success) | ||
627 | */ | ||
628 | static void | ||
629 | move_attr_finished (void *cls, int32_t success, const char *emsg) | ||
630 | { | ||
631 | struct RECLAIM_TICKETS_RevokeHandle *rvk = cls; | ||
632 | char *label; | ||
633 | |||
634 | rvk->ns_qe = NULL; | ||
635 | if (GNUNET_SYSERR == success) | ||
636 | { | ||
637 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error moving attribute: %s\n", emsg); | ||
638 | rvk->cb (rvk->cb_cls, GNUNET_SYSERR); | ||
639 | cleanup_rvk (rvk); | ||
640 | return; | ||
641 | } | ||
642 | label = GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->old_id, | ||
643 | sizeof(rvk->move_attr->old_id)); | ||
644 | GNUNET_assert (NULL != label); | ||
645 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing attribute %s\n", label); | ||
646 | rvk->ns_qe = GNUNET_NAMESTORE_records_store (nsh, | ||
647 | &rvk->identity, | ||
648 | label, | ||
649 | 0, | ||
650 | NULL, | ||
651 | &del_attr_finished, | ||
652 | rvk); | ||
653 | GNUNET_free (label); | ||
654 | } | ||
655 | |||
656 | |||
657 | /** | ||
658 | * Got the referenced attribute. Updating the ID | ||
659 | * | ||
660 | * @param cls handle to the operation | ||
661 | * @param zone issuer identity | ||
662 | * @param label attribute ID | ||
663 | * @param rd_count size of record set (should be 1) | ||
664 | * @param rd record set (the attribute) | ||
665 | */ | ||
666 | static void | ||
667 | rvk_move_attr_cb (void *cls, | ||
668 | const struct GNUNET_IDENTITY_PrivateKey *zone, | ||
669 | const char *label, | ||
670 | unsigned int rd_count, | ||
671 | const struct GNUNET_GNSRECORD_Data *rd) | ||
672 | { | ||
673 | struct RECLAIM_TICKETS_RevokeHandle *rvk = cls; | ||
674 | struct GNUNET_GNSRECORD_Data new_rd[rd_count]; | ||
675 | struct RevokedAttributeEntry *le; | ||
676 | char *new_label; | ||
677 | char *attr_data; | ||
678 | |||
679 | rvk->ns_qe = NULL; | ||
680 | if (0 == rd_count) | ||
681 | { | ||
682 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
683 | "The claim %s no longer exists!\n", | ||
684 | label); | ||
685 | le = rvk->move_attr; | ||
686 | rvk->move_attr = le->next; | ||
687 | GNUNET_CONTAINER_DLL_remove (rvk->attrs_head, rvk->attrs_tail, le); | ||
688 | GNUNET_free (le); | ||
689 | GNUNET_SCHEDULER_add_now (&move_attrs_cont, rvk); | ||
690 | return; | ||
691 | } | ||
692 | GNUNET_RECLAIM_id_generate (&rvk->move_attr->new_id); | ||
693 | new_label = | ||
694 | GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->new_id, | ||
695 | sizeof (rvk->move_attr->new_id)); | ||
696 | |||
697 | attr_data = NULL; | ||
698 | // new_rd = *rd; | ||
699 | for (int i = 0; i < rd_count; i++) | ||
700 | { | ||
701 | if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE == rd[i].record_type) | ||
702 | { | ||
703 | /** find a new place for this attribute **/ | ||
704 | struct GNUNET_RECLAIM_Attribute *claim; | ||
705 | GNUNET_RECLAIM_attribute_deserialize (rd[i].data, | ||
706 | rd[i].data_size, | ||
707 | &claim); | ||
708 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
709 | "Attribute to update: Name=%s\n", | ||
710 | claim->name); | ||
711 | claim->id = rvk->move_attr->new_id; | ||
712 | new_rd[i].data_size = GNUNET_RECLAIM_attribute_serialize_get_size (claim); | ||
713 | attr_data = GNUNET_malloc (rd[i].data_size); | ||
714 | new_rd[i].data_size = GNUNET_RECLAIM_attribute_serialize (claim, | ||
715 | attr_data); | ||
716 | new_rd[i].data = attr_data; | ||
717 | new_rd[i].record_type = rd[i].record_type; | ||
718 | new_rd[i].flags = rd[i].flags; | ||
719 | new_rd[i].expiration_time = rd[i].expiration_time; | ||
720 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding attribute %s\n", new_label); | ||
721 | GNUNET_free (claim); | ||
722 | } | ||
723 | else if (GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL == rd[i].record_type) | ||
724 | { | ||
725 | struct GNUNET_RECLAIM_Credential *credential; | ||
726 | credential = GNUNET_RECLAIM_credential_deserialize (rd[i].data, | ||
727 | rd[i].data_size); | ||
728 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
729 | "Credential to update: Name=%s\n", | ||
730 | credential->name); | ||
731 | credential->id = rvk->move_attr->new_id; | ||
732 | new_rd[i].data_size = | ||
733 | GNUNET_RECLAIM_credential_serialize_get_size (credential); | ||
734 | attr_data = GNUNET_malloc (rd[i].data_size); | ||
735 | new_rd[i].data_size = GNUNET_RECLAIM_credential_serialize (credential, | ||
736 | attr_data); | ||
737 | new_rd[i].data = attr_data; | ||
738 | new_rd[i].record_type = rd[i].record_type; | ||
739 | new_rd[i].flags = rd[i].flags; | ||
740 | new_rd[i].expiration_time = rd[i].expiration_time; | ||
741 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding credential %s\n", | ||
742 | new_label); | ||
743 | GNUNET_free (credential); | ||
744 | } | ||
745 | } | ||
746 | rvk->ns_qe = GNUNET_NAMESTORE_records_store (nsh, | ||
747 | &rvk->identity, | ||
748 | new_label, | ||
749 | rd_count, | ||
750 | new_rd, | ||
751 | &move_attr_finished, | ||
752 | rvk); | ||
753 | GNUNET_free (new_label); | ||
754 | GNUNET_free (attr_data); | ||
755 | } | ||
756 | |||
757 | |||
758 | /** | ||
759 | * We change every attribute ID of the ticket attributes we | ||
760 | * want to revoke. | ||
761 | * When we are done, we need to update any other ticket which | ||
762 | * included references to any of the changed attributes. | ||
763 | * | ||
764 | * @param rvk handle to the operation | ||
765 | */ | ||
766 | static void | ||
767 | move_attrs (struct RECLAIM_TICKETS_RevokeHandle *rvk) | ||
768 | { | ||
769 | char *label; | ||
770 | |||
771 | if (NULL == rvk->move_attr) | ||
772 | { | ||
773 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Finished moving attributes\n"); | ||
774 | rvk->ns_it = | ||
775 | GNUNET_NAMESTORE_zone_iteration_start (nsh, | ||
776 | &rvk->identity, | ||
777 | &rvk_ns_iter_err, | ||
778 | rvk, | ||
779 | &rvk_ticket_update, | ||
780 | rvk, | ||
781 | &rvk_ticket_update_finished, | ||
782 | rvk); | ||
783 | return; | ||
784 | } | ||
785 | label = GNUNET_STRINGS_data_to_string_alloc (&rvk->move_attr->old_id, | ||
786 | sizeof (rvk->move_attr->old_id)); | ||
787 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Moving claim %s\n", label); | ||
788 | |||
789 | rvk->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh, | ||
790 | &rvk->identity, | ||
791 | label, | ||
792 | &rvk_ns_err, | ||
793 | rvk, | ||
794 | &rvk_move_attr_cb, | ||
795 | rvk); | ||
796 | GNUNET_free (label); | ||
797 | } | ||
798 | |||
799 | |||
800 | /** | ||
801 | * Finished deleting ticket and attribute references. | ||
802 | * Abort on failure. | ||
803 | * Else, we start changing every attribute ID in the | ||
804 | * found attribute references so that access is no longer | ||
805 | * possible. | ||
806 | * | ||
807 | * @param cls handle to the operation | ||
808 | * @param success Namestore operation return value | ||
809 | * @param emsg error message (NULL on success) | ||
810 | */ | ||
811 | static void | ||
812 | remove_ticket_cont (void *cls, int32_t success, const char *emsg) | ||
813 | { | ||
814 | struct RECLAIM_TICKETS_RevokeHandle *rvk = cls; | ||
815 | |||
816 | rvk->ns_qe = NULL; | ||
817 | if (GNUNET_SYSERR == success) | ||
818 | { | ||
819 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", emsg); | ||
820 | rvk->cb (rvk->cb_cls, GNUNET_SYSERR); | ||
821 | cleanup_rvk (rvk); | ||
822 | return; | ||
823 | } | ||
824 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleted ticket\n"); | ||
825 | if (0 == rvk->ticket_attrs) | ||
826 | { | ||
827 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
828 | "No attributes to move... strange\n"); | ||
829 | rvk->cb (rvk->cb_cls, GNUNET_OK); | ||
830 | cleanup_rvk (rvk); | ||
831 | return; | ||
832 | } | ||
833 | rvk->move_attr = rvk->attrs_head; | ||
834 | move_attrs (rvk); | ||
835 | } | ||
836 | |||
837 | |||
838 | /** | ||
839 | * We found the attribute references. | ||
840 | * Store them for later and remove the record set. | ||
841 | * | ||
842 | * @param cls handle to the operation | ||
843 | * @param zone the issuer key | ||
844 | * @param label ticket rnd | ||
845 | * @param rd_cound size of record set | ||
846 | * @param rd record set | ||
847 | */ | ||
848 | static void | ||
849 | revoke_attrs_cb (void *cls, | ||
850 | const struct GNUNET_IDENTITY_PrivateKey *zone, | ||
851 | const char *label, | ||
852 | unsigned int rd_count, | ||
853 | const struct GNUNET_GNSRECORD_Data *rd) | ||
854 | |||
855 | { | ||
856 | struct RECLAIM_TICKETS_RevokeHandle *rvk = cls; | ||
857 | struct RevokedAttributeEntry *le; | ||
858 | |||
859 | rvk->ns_qe = NULL; | ||
860 | /** | ||
861 | * Temporarily store attribute references. | ||
862 | * We need it later. | ||
863 | */ | ||
864 | for (int i = 0; i < rd_count; i++) | ||
865 | { | ||
866 | if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF != rd[i].record_type) | ||
867 | continue; | ||
868 | le = GNUNET_new (struct RevokedAttributeEntry); | ||
869 | le->old_id = *((struct GNUNET_RECLAIM_Identifier *) rd[i].data); | ||
870 | GNUNET_CONTAINER_DLL_insert (rvk->attrs_head, rvk->attrs_tail, le); | ||
871 | rvk->ticket_attrs++; | ||
872 | } | ||
873 | |||
874 | /** Remove attribute references **/ | ||
875 | rvk->ns_qe = GNUNET_NAMESTORE_records_store (nsh, | ||
876 | &rvk->identity, | ||
877 | label, | ||
878 | 0, | ||
879 | NULL, | ||
880 | &remove_ticket_cont, | ||
881 | rvk); | ||
882 | } | ||
883 | |||
884 | |||
885 | /** | ||
886 | * Failed to query namestore. Abort operation | ||
887 | * | ||
888 | * @param cls handle to the operation | ||
889 | */ | ||
890 | static void | ||
891 | rvk_attrs_err_cb (void *cls) | ||
892 | { | ||
893 | struct RECLAIM_TICKETS_RevokeHandle *rvk = cls; | ||
894 | |||
895 | rvk->cb (rvk->cb_cls, GNUNET_SYSERR); | ||
896 | cleanup_rvk (rvk); | ||
897 | } | ||
898 | |||
899 | |||
900 | /** | ||
901 | * Revoke a ticket. | ||
902 | * We start by looking up attribute references in order | ||
903 | * to change attribute IDs. | ||
904 | * | ||
905 | * @param ticket ticket to revoke | ||
906 | * @param identity private key of issuer | ||
907 | * @param cb revocation status callback | ||
908 | * @param cb_cls callback closure | ||
909 | * @return handle to the operation | ||
910 | */ | ||
911 | struct RECLAIM_TICKETS_RevokeHandle * | ||
912 | RECLAIM_TICKETS_revoke (const struct GNUNET_RECLAIM_Ticket *ticket, | ||
913 | const struct GNUNET_IDENTITY_PrivateKey *identity, | ||
914 | RECLAIM_TICKETS_RevokeCallback cb, | ||
915 | void *cb_cls) | ||
916 | { | ||
917 | struct RECLAIM_TICKETS_RevokeHandle *rvk; | ||
918 | char *label; | ||
919 | |||
920 | rvk = GNUNET_new (struct RECLAIM_TICKETS_RevokeHandle); | ||
921 | rvk->cb = cb; | ||
922 | rvk->cb_cls = cb_cls; | ||
923 | rvk->identity = *identity; | ||
924 | rvk->ticket = *ticket; | ||
925 | GNUNET_IDENTITY_key_get_public (&rvk->identity, &rvk->ticket.identity); | ||
926 | /** Get shared attributes **/ | ||
927 | label = GNUNET_STRINGS_data_to_string_alloc (&ticket->rnd, | ||
928 | sizeof(ticket->rnd)); | ||
929 | GNUNET_assert (NULL != label); | ||
930 | rvk->ns_qe = GNUNET_NAMESTORE_records_lookup (nsh, | ||
931 | identity, | ||
932 | label, | ||
933 | &rvk_attrs_err_cb, | ||
934 | rvk, | ||
935 | &revoke_attrs_cb, | ||
936 | rvk); | ||
937 | GNUNET_free (label); | ||
938 | return rvk; | ||
939 | } | ||
940 | |||
941 | |||
942 | /** | ||
943 | * Cancel a revocation. | ||
944 | * | ||
945 | * @param rh handle to the operation | ||
946 | */ | ||
947 | void | ||
948 | RECLAIM_TICKETS_revoke_cancel (struct RECLAIM_TICKETS_RevokeHandle *rh) | ||
949 | { | ||
950 | GNUNET_assert (NULL != rh); | ||
951 | cleanup_rvk (rh); | ||
952 | } | ||
953 | |||
954 | |||
955 | /******************************* | ||
956 | * Ticket consume | ||
957 | *******************************/ | ||
958 | |||
959 | /** | ||
960 | * Cleanup ticket consume handle | ||
961 | * | ||
962 | * @param cth the handle to clean up | ||
963 | */ | ||
964 | static void | ||
965 | cleanup_cth (struct RECLAIM_TICKETS_ConsumeHandle *cth) | ||
966 | { | ||
967 | struct ParallelLookup *lu; | ||
968 | |||
969 | if (NULL != cth->lookup_request) | ||
970 | GNUNET_GNS_lookup_cancel (cth->lookup_request); | ||
971 | if (NULL != cth->kill_task) | ||
972 | GNUNET_SCHEDULER_cancel (cth->kill_task); | ||
973 | while (NULL != (lu = cth->parallel_lookups_head)) | ||
974 | { | ||
975 | if (NULL != lu->lookup_request) | ||
976 | GNUNET_GNS_lookup_cancel (lu->lookup_request); | ||
977 | GNUNET_free (lu->label); | ||
978 | GNUNET_CONTAINER_DLL_remove (cth->parallel_lookups_head, | ||
979 | cth->parallel_lookups_tail, | ||
980 | lu); | ||
981 | GNUNET_free (lu); | ||
982 | } | ||
983 | |||
984 | if (NULL != cth->attrs) | ||
985 | GNUNET_RECLAIM_attribute_list_destroy (cth->attrs); | ||
986 | if (NULL != cth->presentations) | ||
987 | GNUNET_RECLAIM_presentation_list_destroy (cth->presentations); | ||
988 | GNUNET_free (cth); | ||
989 | } | ||
990 | |||
991 | |||
992 | /** | ||
993 | * We found an attribute record. | ||
994 | * | ||
995 | * @param cls handle to the operation | ||
996 | * @param rd_cound size of record set | ||
997 | * @param rd record set | ||
998 | */ | ||
999 | static void | ||
1000 | process_parallel_lookup_result (void *cls, | ||
1001 | uint32_t rd_count, | ||
1002 | const struct GNUNET_GNSRECORD_Data *rd) | ||
1003 | { | ||
1004 | struct ParallelLookup *parallel_lookup = cls; | ||
1005 | struct RECLAIM_TICKETS_ConsumeHandle *cth = parallel_lookup->handle; | ||
1006 | struct GNUNET_RECLAIM_AttributeListEntry *attr_le; | ||
1007 | |||
1008 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1009 | "Parallel lookup finished (count=%u)\n", | ||
1010 | rd_count); | ||
1011 | |||
1012 | GNUNET_CONTAINER_DLL_remove (cth->parallel_lookups_head, | ||
1013 | cth->parallel_lookups_tail, | ||
1014 | parallel_lookup); | ||
1015 | GNUNET_free (parallel_lookup->label); | ||
1016 | |||
1017 | GNUNET_STATISTICS_update (stats, | ||
1018 | "attribute_lookup_time_total", | ||
1019 | GNUNET_TIME_absolute_get_duration ( | ||
1020 | parallel_lookup->lookup_start_time) | ||
1021 | .rel_value_us, | ||
1022 | GNUNET_YES); | ||
1023 | GNUNET_STATISTICS_update (stats, "attribute_lookups_count", 1, GNUNET_YES); | ||
1024 | |||
1025 | |||
1026 | GNUNET_free (parallel_lookup); | ||
1027 | if (0 == rd_count) | ||
1028 | GNUNET_break (0); | ||
1029 | // REMARK: It is possible now to find rd_count > 1 | ||
1030 | for (int i = 0; i < rd_count; i++) | ||
1031 | { | ||
1032 | if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE != rd[i].record_type) | ||
1033 | continue; | ||
1034 | attr_le = GNUNET_new (struct GNUNET_RECLAIM_AttributeListEntry); | ||
1035 | GNUNET_RECLAIM_attribute_deserialize (rd[i].data, rd[i].data_size, | ||
1036 | &attr_le->attribute); | ||
1037 | GNUNET_CONTAINER_DLL_insert (cth->attrs->list_head, | ||
1038 | cth->attrs->list_tail, | ||
1039 | attr_le); | ||
1040 | } | ||
1041 | if (NULL != cth->parallel_lookups_head) | ||
1042 | return; // Wait for more | ||
1043 | /* Else we are done */ | ||
1044 | cth->cb (cth->cb_cls, &cth->ticket.identity, | ||
1045 | cth->attrs, cth->presentations, GNUNET_OK, NULL); | ||
1046 | cleanup_cth (cth); | ||
1047 | } | ||
1048 | |||
1049 | |||
1050 | /** | ||
1051 | * Cancel the lookups for attribute records | ||
1052 | * | ||
1053 | * @param cls handle to the operation | ||
1054 | */ | ||
1055 | static void | ||
1056 | abort_parallel_lookups (void *cls) | ||
1057 | { | ||
1058 | struct RECLAIM_TICKETS_ConsumeHandle *cth = cls; | ||
1059 | struct ParallelLookup *lu; | ||
1060 | struct ParallelLookup *tmp; | ||
1061 | |||
1062 | cth->kill_task = NULL; | ||
1063 | for (lu = cth->parallel_lookups_head; NULL != lu;) | ||
1064 | { | ||
1065 | GNUNET_GNS_lookup_cancel (lu->lookup_request); | ||
1066 | GNUNET_free (lu->label); | ||
1067 | tmp = lu->next; | ||
1068 | GNUNET_CONTAINER_DLL_remove (cth->parallel_lookups_head, | ||
1069 | cth->parallel_lookups_tail, | ||
1070 | lu); | ||
1071 | GNUNET_free (lu); | ||
1072 | lu = tmp; | ||
1073 | } | ||
1074 | cth->cb (cth->cb_cls, NULL, NULL, NULL, GNUNET_SYSERR, "Aborted"); | ||
1075 | } | ||
1076 | |||
1077 | |||
1078 | /** | ||
1079 | * GNS result with attribute references. | ||
1080 | * For each result, we start a (parallel) lookup of the actual | ||
1081 | * attribute record under the referenced label. | ||
1082 | * | ||
1083 | * @param cls handle to the operation | ||
1084 | * @param rd_cound size of the record set | ||
1085 | * @param rd record set | ||
1086 | */ | ||
1087 | static void | ||
1088 | lookup_authz_cb (void *cls, | ||
1089 | uint32_t rd_count, | ||
1090 | const struct GNUNET_GNSRECORD_Data *rd) | ||
1091 | { | ||
1092 | struct RECLAIM_TICKETS_ConsumeHandle *cth = cls; | ||
1093 | struct ParallelLookup *parallel_lookup; | ||
1094 | char *lbl; | ||
1095 | struct GNUNET_RECLAIM_PresentationListEntry *ale; | ||
1096 | |||
1097 | cth->lookup_request = NULL; | ||
1098 | |||
1099 | GNUNET_STATISTICS_update (stats, | ||
1100 | "reclaim_authz_lookup_time_total", | ||
1101 | GNUNET_TIME_absolute_get_duration ( | ||
1102 | cth->lookup_start_time) | ||
1103 | .rel_value_us, | ||
1104 | GNUNET_YES); | ||
1105 | GNUNET_STATISTICS_update (stats, | ||
1106 | "reclaim_authz_lookups_count", | ||
1107 | 1, | ||
1108 | GNUNET_YES); | ||
1109 | |||
1110 | for (int i = 0; i < rd_count; i++) | ||
1111 | { | ||
1112 | /** | ||
1113 | * Check if record is a credential presentation or an attribute | ||
1114 | * reference. | ||
1115 | */ | ||
1116 | switch (rd[i].record_type) | ||
1117 | { | ||
1118 | case GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION: | ||
1119 | ale = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry); | ||
1120 | ale->presentation = | ||
1121 | GNUNET_RECLAIM_presentation_deserialize (rd[i].data, | ||
1122 | rd[i].data_size); | ||
1123 | GNUNET_CONTAINER_DLL_insert (cth->presentations->list_head, | ||
1124 | cth->presentations->list_tail, | ||
1125 | ale); | ||
1126 | break; | ||
1127 | case GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF: | ||
1128 | lbl = GNUNET_STRINGS_data_to_string_alloc (rd[i].data, rd[i].data_size); | ||
1129 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ticket reference found %s\n", lbl); | ||
1130 | parallel_lookup = GNUNET_new (struct ParallelLookup); | ||
1131 | parallel_lookup->handle = cth; | ||
1132 | parallel_lookup->label = lbl; | ||
1133 | parallel_lookup->lookup_start_time = GNUNET_TIME_absolute_get (); | ||
1134 | parallel_lookup->lookup_request = | ||
1135 | GNUNET_GNS_lookup (gns, | ||
1136 | lbl, | ||
1137 | &cth->ticket.identity, | ||
1138 | GNUNET_GNSRECORD_TYPE_ANY, | ||
1139 | GNUNET_GNS_LO_DEFAULT, | ||
1140 | &process_parallel_lookup_result, | ||
1141 | parallel_lookup); | ||
1142 | GNUNET_CONTAINER_DLL_insert (cth->parallel_lookups_head, | ||
1143 | cth->parallel_lookups_tail, | ||
1144 | parallel_lookup); | ||
1145 | break; | ||
1146 | default: | ||
1147 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1148 | "Ignoring unknown record type %d", rd[i].record_type); | ||
1149 | } | ||
1150 | } | ||
1151 | /** | ||
1152 | * We started lookups. Add a timeout task. | ||
1153 | * FIXME: Really needed here? | ||
1154 | */ | ||
1155 | if (NULL != cth->parallel_lookups_head) | ||
1156 | { | ||
1157 | cth->kill_task = GNUNET_SCHEDULER_add_delayed ( | ||
1158 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 3), | ||
1159 | &abort_parallel_lookups, | ||
1160 | cth); | ||
1161 | return; | ||
1162 | } | ||
1163 | /** | ||
1164 | * No references found, return empty attribute list | ||
1165 | */ | ||
1166 | cth->cb (cth->cb_cls, &cth->ticket.identity, | ||
1167 | cth->attrs, NULL, GNUNET_OK, NULL); | ||
1168 | cleanup_cth (cth); | ||
1169 | } | ||
1170 | |||
1171 | |||
1172 | /** | ||
1173 | * Consume a ticket. | ||
1174 | * We first looking attribute references under the label | ||
1175 | * ticket.rnd in GNS. | ||
1176 | * | ||
1177 | * @param id the audience of the ticket | ||
1178 | * @param ticket the ticket to consume | ||
1179 | * @param cb callback to call with attributes of ticket | ||
1180 | * @param cb_cls callback closure | ||
1181 | * @return handle to the operation | ||
1182 | */ | ||
1183 | struct RECLAIM_TICKETS_ConsumeHandle * | ||
1184 | RECLAIM_TICKETS_consume (const struct GNUNET_IDENTITY_PrivateKey *id, | ||
1185 | const struct GNUNET_RECLAIM_Ticket *ticket, | ||
1186 | RECLAIM_TICKETS_ConsumeCallback cb, | ||
1187 | void *cb_cls) | ||
1188 | { | ||
1189 | struct RECLAIM_TICKETS_ConsumeHandle *cth; | ||
1190 | char *label; | ||
1191 | |||
1192 | cth = GNUNET_new (struct RECLAIM_TICKETS_ConsumeHandle); | ||
1193 | |||
1194 | cth->identity = *id; | ||
1195 | GNUNET_IDENTITY_key_get_public (&cth->identity, &cth->identity_pub); | ||
1196 | cth->attrs = GNUNET_new (struct GNUNET_RECLAIM_AttributeList); | ||
1197 | cth->presentations = GNUNET_new (struct GNUNET_RECLAIM_PresentationList); | ||
1198 | cth->ticket = *ticket; | ||
1199 | cth->cb = cb; | ||
1200 | cth->cb_cls = cb_cls; | ||
1201 | label = | ||
1202 | GNUNET_STRINGS_data_to_string_alloc (&cth->ticket.rnd, | ||
1203 | sizeof(cth->ticket.rnd)); | ||
1204 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1205 | "Looking for AuthZ info under %s\n", | ||
1206 | label); | ||
1207 | cth->lookup_start_time = GNUNET_TIME_absolute_get (); | ||
1208 | cth->lookup_request = | ||
1209 | GNUNET_GNS_lookup (gns, | ||
1210 | label, | ||
1211 | &cth->ticket.identity, | ||
1212 | GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF, | ||
1213 | GNUNET_GNS_LO_DEFAULT, | ||
1214 | &lookup_authz_cb, | ||
1215 | cth); | ||
1216 | GNUNET_free (label); | ||
1217 | return cth; | ||
1218 | } | ||
1219 | |||
1220 | |||
1221 | /** | ||
1222 | * Cancel a consume operation | ||
1223 | * | ||
1224 | * @param cth the operation to cancel | ||
1225 | */ | ||
1226 | void | ||
1227 | RECLAIM_TICKETS_consume_cancel (struct RECLAIM_TICKETS_ConsumeHandle *cth) | ||
1228 | { | ||
1229 | cleanup_cth (cth); | ||
1230 | return; | ||
1231 | } | ||
1232 | |||
1233 | |||
1234 | /******************************* | ||
1235 | * Ticket issue | ||
1236 | *******************************/ | ||
1237 | |||
1238 | /** | ||
1239 | * Cleanup ticket consume handle | ||
1240 | * @param handle the handle to clean up | ||
1241 | */ | ||
1242 | static void | ||
1243 | cleanup_issue_handle (struct TicketIssueHandle *handle) | ||
1244 | { | ||
1245 | if (NULL != handle->ns_qe) | ||
1246 | GNUNET_NAMESTORE_cancel (handle->ns_qe); | ||
1247 | GNUNET_free (handle); | ||
1248 | } | ||
1249 | |||
1250 | |||
1251 | /** | ||
1252 | * Store finished, abort on error. | ||
1253 | * Else, return new ticket to caller. | ||
1254 | * | ||
1255 | * @param cls handle to the operation | ||
1256 | * @param success store operation result | ||
1257 | * @param emsg error message (or NULL on success) | ||
1258 | */ | ||
1259 | static void | ||
1260 | store_ticket_issue_cont (void *cls, int32_t success, const char *emsg) | ||
1261 | { | ||
1262 | struct TicketIssueHandle *handle = cls; | ||
1263 | |||
1264 | handle->ns_qe = NULL; | ||
1265 | if (GNUNET_SYSERR == success) | ||
1266 | { | ||
1267 | handle->cb (handle->cb_cls, | ||
1268 | &handle->ticket, | ||
1269 | NULL, | ||
1270 | GNUNET_SYSERR, | ||
1271 | "Error storing AuthZ ticket in GNS"); | ||
1272 | return; | ||
1273 | } | ||
1274 | handle->cb (handle->cb_cls, | ||
1275 | &handle->ticket, | ||
1276 | handle->presentations, | ||
1277 | GNUNET_OK, NULL); | ||
1278 | cleanup_issue_handle (handle); | ||
1279 | } | ||
1280 | |||
1281 | |||
1282 | /** | ||
1283 | * Issue a new ticket. | ||
1284 | * We store references to attribute record labels and the ticket itself | ||
1285 | * under the label base64(ticket.rnd). | ||
1286 | * | ||
1287 | * @param ih handle to the operation containing relevant metadata | ||
1288 | */ | ||
1289 | static void | ||
1290 | issue_ticket (struct TicketIssueHandle *ih) | ||
1291 | { | ||
1292 | struct GNUNET_RECLAIM_AttributeListEntry *le; | ||
1293 | struct GNUNET_RECLAIM_PresentationListEntry *ple; | ||
1294 | struct GNUNET_GNSRECORD_Data *attrs_record; | ||
1295 | char *label; | ||
1296 | int i; | ||
1297 | int j; | ||
1298 | int attrs_count = 0; | ||
1299 | |||
1300 | for (le = ih->attrs->list_head; NULL != le; le = le->next) | ||
1301 | attrs_count++; | ||
1302 | |||
1303 | // Worst case we have one presentation per attribute | ||
1304 | attrs_record = | ||
1305 | GNUNET_malloc (2 * attrs_count * sizeof(struct GNUNET_GNSRECORD_Data)); | ||
1306 | i = 0; | ||
1307 | for (le = ih->attrs->list_head; NULL != le; le = le->next) | ||
1308 | { | ||
1309 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1310 | "Adding list entry: %s\n", le->attribute->name); | ||
1311 | |||
1312 | attrs_record[i].data = &le->attribute->id; | ||
1313 | attrs_record[i].data_size = sizeof(le->attribute->id); | ||
1314 | attrs_record[i].expiration_time = ticket_refresh_interval.rel_value_us; | ||
1315 | attrs_record[i].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF; | ||
1316 | attrs_record[i].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; | ||
1317 | i++; | ||
1318 | if (GNUNET_NO == GNUNET_RECLAIM_id_is_zero (&le->attribute->credential)) | ||
1319 | { | ||
1320 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1321 | "Attribute is backed by credential. Adding...\n"); | ||
1322 | struct GNUNET_RECLAIM_Presentation *presentation = NULL; | ||
1323 | for (j = 0; j < i; j++) | ||
1324 | { | ||
1325 | if (attrs_record[j].record_type | ||
1326 | != GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION) | ||
1327 | continue; | ||
1328 | presentation = GNUNET_RECLAIM_presentation_deserialize ( | ||
1329 | attrs_record[j].data, | ||
1330 | attrs_record[j]. | ||
1331 | data_size); | ||
1332 | if (NULL == presentation) | ||
1333 | { | ||
1334 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1335 | "Failed to deserialize presentation\n"); | ||
1336 | continue; | ||
1337 | } | ||
1338 | if (0 == memcmp (&presentation->credential_id, | ||
1339 | &le->attribute->credential, | ||
1340 | sizeof (le->attribute->credential))) | ||
1341 | break; | ||
1342 | GNUNET_free (presentation); | ||
1343 | presentation = NULL; | ||
1344 | } | ||
1345 | if (NULL != presentation) | ||
1346 | { | ||
1347 | GNUNET_free (presentation); | ||
1348 | continue; // Skip as we have already added this credential presentation. | ||
1349 | } | ||
1350 | for (ple = ih->presentations->list_head; NULL != ple; ple = ple->next) | ||
1351 | { | ||
1352 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1353 | "Checking presentation....\n"); | ||
1354 | |||
1355 | if (0 != memcmp (&le->attribute->credential, | ||
1356 | &ple->presentation->credential_id, | ||
1357 | sizeof (le->attribute->credential))) | ||
1358 | { | ||
1359 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1360 | "Presentation does not match credential ID.\n"); | ||
1361 | continue; | ||
1362 | } | ||
1363 | char *pres_buf; | ||
1364 | size_t pres_size; | ||
1365 | |||
1366 | pres_size = | ||
1367 | GNUNET_RECLAIM_presentation_serialize_get_size (ple->presentation); | ||
1368 | pres_buf = GNUNET_malloc (pres_size); | ||
1369 | GNUNET_RECLAIM_presentation_serialize (ple->presentation, | ||
1370 | pres_buf); | ||
1371 | attrs_record[i].data = pres_buf; | ||
1372 | attrs_record[i].data_size = pres_size; | ||
1373 | attrs_record[i].expiration_time = | ||
1374 | ticket_refresh_interval.rel_value_us; | ||
1375 | attrs_record[i].record_type = | ||
1376 | GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION; | ||
1377 | attrs_record[i].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; | ||
1378 | i++; | ||
1379 | break; | ||
1380 | } | ||
1381 | } | ||
1382 | } | ||
1383 | attrs_record[i].data = &ih->ticket; | ||
1384 | attrs_record[i].data_size = sizeof(struct GNUNET_RECLAIM_Ticket); | ||
1385 | attrs_record[i].expiration_time = ticket_refresh_interval.rel_value_us; | ||
1386 | attrs_record[i].record_type = GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET; | ||
1387 | attrs_record[i].flags = | ||
1388 | GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION | GNUNET_GNSRECORD_RF_PRIVATE; | ||
1389 | i++; | ||
1390 | |||
1391 | label = | ||
1392 | GNUNET_STRINGS_data_to_string_alloc (&ih->ticket.rnd, | ||
1393 | sizeof(ih->ticket.rnd)); | ||
1394 | // Publish record | ||
1395 | ih->ns_qe = GNUNET_NAMESTORE_records_store (nsh, | ||
1396 | &ih->identity, | ||
1397 | label, | ||
1398 | i, | ||
1399 | attrs_record, | ||
1400 | &store_ticket_issue_cont, | ||
1401 | ih); | ||
1402 | for (j = 0; j < i; j++) | ||
1403 | { | ||
1404 | if (attrs_record[j].record_type | ||
1405 | != GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION) | ||
1406 | continue; | ||
1407 | // Yes, we are allowed to do this because we allocated it above | ||
1408 | char *ptr = (char*) attrs_record[j].data; | ||
1409 | GNUNET_free (ptr); | ||
1410 | } | ||
1411 | GNUNET_free (attrs_record); | ||
1412 | GNUNET_free (label); | ||
1413 | } | ||
1414 | |||
1415 | |||
1416 | /************************************************* | ||
1417 | * Ticket iteration (finding a specific ticket) | ||
1418 | *************************************************/ | ||
1419 | |||
1420 | |||
1421 | /** | ||
1422 | * Namestore error on issue. Abort. | ||
1423 | * | ||
1424 | * @param cls handle to the operation | ||
1425 | */ | ||
1426 | static void | ||
1427 | filter_tickets_error_cb (void *cls) | ||
1428 | { | ||
1429 | struct TicketIssueHandle *tih = cls; | ||
1430 | |||
1431 | tih->ns_it = NULL; | ||
1432 | tih->cb (tih->cb_cls, | ||
1433 | &tih->ticket, | ||
1434 | NULL, | ||
1435 | GNUNET_SYSERR, | ||
1436 | "Error storing AuthZ ticket in GNS"); | ||
1437 | cleanup_issue_handle (tih); | ||
1438 | } | ||
1439 | |||
1440 | |||
1441 | /** | ||
1442 | * Iterator over records. | ||
1443 | * Check if any previously issued ticket already | ||
1444 | * matches what we need to prevent duplicates and | ||
1445 | * improve resolution synergy. | ||
1446 | * | ||
1447 | * @param cls handle to the operation | ||
1448 | * @param zone issuer identity | ||
1449 | * @param label ticket rnd | ||
1450 | * @param rd_count size of record set | ||
1451 | * @param rd record set | ||
1452 | */ | ||
1453 | static void | ||
1454 | filter_tickets_cb (void *cls, | ||
1455 | const struct GNUNET_IDENTITY_PrivateKey *zone, | ||
1456 | const char *label, | ||
1457 | unsigned int rd_count, | ||
1458 | const struct GNUNET_GNSRECORD_Data *rd) | ||
1459 | { | ||
1460 | struct TicketIssueHandle *tih = cls; | ||
1461 | struct GNUNET_RECLAIM_Ticket *ticket = NULL; | ||
1462 | struct GNUNET_RECLAIM_Presentation *presentation; | ||
1463 | struct GNUNET_RECLAIM_PresentationList *ticket_presentations; | ||
1464 | struct GNUNET_RECLAIM_Credential *cred; | ||
1465 | struct GNUNET_RECLAIM_PresentationListEntry *ple; | ||
1466 | struct GNUNET_RECLAIM_AttributeListEntry *le; | ||
1467 | unsigned int attr_cnt = 0; | ||
1468 | unsigned int pres_cnt = 0; | ||
1469 | |||
1470 | for (le = tih->attrs->list_head; NULL != le; le = le->next) | ||
1471 | { | ||
1472 | attr_cnt++; | ||
1473 | if (GNUNET_NO == GNUNET_RECLAIM_id_is_zero (&le->attribute->credential)) | ||
1474 | pres_cnt++; | ||
1475 | } | ||
1476 | |||
1477 | // ticket search | ||
1478 | unsigned int found_attrs_cnt = 0; | ||
1479 | unsigned int found_pres_cnt = 0; | ||
1480 | ticket_presentations = GNUNET_new (struct GNUNET_RECLAIM_PresentationList); | ||
1481 | |||
1482 | for (int i = 0; i < rd_count; i++) | ||
1483 | { | ||
1484 | // found ticket | ||
1485 | if (GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET == rd[i].record_type) | ||
1486 | { | ||
1487 | ticket = (struct GNUNET_RECLAIM_Ticket *) rd[i].data; | ||
1488 | // cmp audience | ||
1489 | if (0 == memcmp (&tih->ticket.audience, | ||
1490 | &ticket->audience, | ||
1491 | sizeof(struct GNUNET_IDENTITY_PublicKey))) | ||
1492 | { | ||
1493 | tih->ticket = *ticket; | ||
1494 | continue; | ||
1495 | } | ||
1496 | ticket = NULL; | ||
1497 | } | ||
1498 | |||
1499 | // cmp requested attributes with ticket attributes | ||
1500 | if (GNUNET_GNSRECORD_TYPE_RECLAIM_ATTRIBUTE_REF == rd[i].record_type) | ||
1501 | { | ||
1502 | for (le = tih->attrs->list_head; NULL != le; le = le->next) | ||
1503 | { | ||
1504 | if (GNUNET_YES == GNUNET_RECLAIM_id_is_equal (rd[i].data, | ||
1505 | &le->attribute->id)) | ||
1506 | found_attrs_cnt++; | ||
1507 | } | ||
1508 | } | ||
1509 | if (GNUNET_GNSRECORD_TYPE_RECLAIM_CREDENTIAL == rd[i].record_type) | ||
1510 | { | ||
1511 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1512 | "Found credential...\n"); | ||
1513 | |||
1514 | for (le = tih->attrs->list_head; NULL != le; le = le->next) | ||
1515 | { | ||
1516 | cred = GNUNET_RECLAIM_credential_deserialize (rd[i].data, | ||
1517 | rd[i].data_size); | ||
1518 | if (GNUNET_YES != GNUNET_RECLAIM_id_is_equal (&cred->id, | ||
1519 | &le->attribute->credential)) | ||
1520 | { | ||
1521 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1522 | "No match.\n"); | ||
1523 | GNUNET_free (cred); | ||
1524 | continue; | ||
1525 | } | ||
1526 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1527 | "Match, creating presentation...\n"); | ||
1528 | if (GNUNET_OK != GNUNET_RECLAIM_credential_get_presentation ( | ||
1529 | cred, | ||
1530 | tih->attrs, | ||
1531 | &presentation)) | ||
1532 | { | ||
1533 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1534 | "Unable to retrieve presentation from credential\n"); | ||
1535 | GNUNET_free (cred); | ||
1536 | continue; | ||
1537 | } | ||
1538 | ple = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry); | ||
1539 | ple->presentation = presentation; | ||
1540 | GNUNET_CONTAINER_DLL_insert (tih->presentations->list_head, | ||
1541 | tih->presentations->list_tail, | ||
1542 | ple); | ||
1543 | GNUNET_free (cred); | ||
1544 | break; | ||
1545 | } | ||
1546 | } | ||
1547 | if (GNUNET_GNSRECORD_TYPE_RECLAIM_PRESENTATION == rd[i].record_type) | ||
1548 | { | ||
1549 | for (le = tih->attrs->list_head; NULL != le; le = le->next) | ||
1550 | { | ||
1551 | presentation = GNUNET_RECLAIM_presentation_deserialize (rd[i].data, | ||
1552 | rd[i].data_size); | ||
1553 | if (NULL == presentation) | ||
1554 | { | ||
1555 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1556 | "Failed to deserialize presentation\n"); | ||
1557 | continue; | ||
1558 | } | ||
1559 | if (GNUNET_YES == GNUNET_RECLAIM_id_is_equal ( | ||
1560 | &presentation->credential_id, | ||
1561 | &le->attribute->credential)) | ||
1562 | { | ||
1563 | found_pres_cnt++; | ||
1564 | ple = GNUNET_new (struct GNUNET_RECLAIM_PresentationListEntry); | ||
1565 | ple->presentation = presentation; | ||
1566 | GNUNET_CONTAINER_DLL_insert (ticket_presentations->list_head, | ||
1567 | ticket_presentations->list_tail, | ||
1568 | ple); | ||
1569 | } | ||
1570 | } | ||
1571 | } | ||
1572 | } | ||
1573 | |||
1574 | /** | ||
1575 | * If we found a matching ticket, return that to the caller and | ||
1576 | * we are done. | ||
1577 | */ | ||
1578 | if ((attr_cnt == found_attrs_cnt) && | ||
1579 | (pres_cnt == found_pres_cnt) && | ||
1580 | (NULL != ticket)) | ||
1581 | { | ||
1582 | GNUNET_NAMESTORE_zone_iteration_stop (tih->ns_it); | ||
1583 | tih->cb (tih->cb_cls, &tih->ticket, ticket_presentations, GNUNET_OK, NULL); | ||
1584 | GNUNET_RECLAIM_presentation_list_destroy (ticket_presentations); | ||
1585 | cleanup_issue_handle (tih); | ||
1586 | return; | ||
1587 | } | ||
1588 | GNUNET_RECLAIM_presentation_list_destroy (ticket_presentations); | ||
1589 | // ticket not found in current record, checking next record set | ||
1590 | GNUNET_NAMESTORE_zone_iterator_next (tih->ns_it, 1); | ||
1591 | } | ||
1592 | |||
1593 | |||
1594 | /** | ||
1595 | * Done iterating over tickets and we apparently did | ||
1596 | * not find an existing, matching ticket. | ||
1597 | * Continue by issuing a new ticket. | ||
1598 | * | ||
1599 | * @param cls handle to the operation | ||
1600 | */ | ||
1601 | static void | ||
1602 | filter_tickets_finished_cb (void *cls) | ||
1603 | { | ||
1604 | struct TicketIssueHandle *tih = cls; | ||
1605 | |||
1606 | GNUNET_IDENTITY_key_get_public (&tih->identity, &tih->ticket.identity); | ||
1607 | GNUNET_RECLAIM_id_generate (&tih->ticket.rnd); | ||
1608 | issue_ticket (tih); | ||
1609 | } | ||
1610 | |||
1611 | |||
1612 | /** | ||
1613 | * Issue a new reclaim ticket, thereby authorizing | ||
1614 | * the audience to access the set of provided attributes. | ||
1615 | * | ||
1616 | * @param identity the issuer | ||
1617 | * @param attrs the attributes to share | ||
1618 | * @param audience the audience to share the attributes with | ||
1619 | * @param cb the callback to call with the ticket result | ||
1620 | * @param cb_cls the callback closure | ||
1621 | * FIXME: Return handle?? | ||
1622 | */ | ||
1623 | void | ||
1624 | RECLAIM_TICKETS_issue (const struct GNUNET_IDENTITY_PrivateKey *identity, | ||
1625 | const struct GNUNET_RECLAIM_AttributeList *attrs, | ||
1626 | const struct GNUNET_IDENTITY_PublicKey *audience, | ||
1627 | RECLAIM_TICKETS_TicketResult cb, | ||
1628 | void *cb_cls) | ||
1629 | { | ||
1630 | struct TicketIssueHandle *tih; | ||
1631 | |||
1632 | tih = GNUNET_new (struct TicketIssueHandle); | ||
1633 | tih->cb = cb; | ||
1634 | tih->cb_cls = cb_cls; | ||
1635 | tih->attrs = GNUNET_RECLAIM_attribute_list_dup (attrs); | ||
1636 | tih->presentations = GNUNET_new (struct GNUNET_RECLAIM_PresentationList); | ||
1637 | tih->identity = *identity; | ||
1638 | tih->ticket.audience = *audience; | ||
1639 | |||
1640 | // First check whether the ticket has already been issued | ||
1641 | tih->ns_it = | ||
1642 | GNUNET_NAMESTORE_zone_iteration_start (nsh, | ||
1643 | &tih->identity, | ||
1644 | &filter_tickets_error_cb, | ||
1645 | tih, | ||
1646 | &filter_tickets_cb, | ||
1647 | tih, | ||
1648 | &filter_tickets_finished_cb, | ||
1649 | tih); | ||
1650 | } | ||
1651 | |||
1652 | |||
1653 | /************************************ | ||
1654 | * Ticket iteration | ||
1655 | ************************************/ | ||
1656 | |||
1657 | /** | ||
1658 | * Cleanup ticket iterator | ||
1659 | * | ||
1660 | * @param iter handle to the iteration | ||
1661 | */ | ||
1662 | static void | ||
1663 | cleanup_iter (struct RECLAIM_TICKETS_Iterator *iter) | ||
1664 | { | ||
1665 | if (NULL != iter->ns_it) | ||
1666 | GNUNET_NAMESTORE_zone_iteration_stop (iter->ns_it); | ||
1667 | GNUNET_free (iter); | ||
1668 | } | ||
1669 | |||
1670 | |||
1671 | /** | ||
1672 | * Return each record of type @GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET | ||
1673 | * to the caller and proceed with the iteration. | ||
1674 | * FIXME: Should we _not_ proceed automatically here? | ||
1675 | * | ||
1676 | * @param cls handle to the iteration | ||
1677 | * @param zone the ticket issuer | ||
1678 | * @param label the ticket rnd | ||
1679 | * @param rd_count number of records in record set | ||
1680 | * @param rd record set containing a ticket | ||
1681 | */ | ||
1682 | static void | ||
1683 | collect_tickets_cb (void *cls, | ||
1684 | const struct GNUNET_IDENTITY_PrivateKey *zone, | ||
1685 | const char *label, | ||
1686 | unsigned int rd_count, | ||
1687 | const struct GNUNET_GNSRECORD_Data *rd) | ||
1688 | { | ||
1689 | struct RECLAIM_TICKETS_Iterator *iter = cls; | ||
1690 | |||
1691 | for (int i = 0; i < rd_count; i++) | ||
1692 | { | ||
1693 | if (GNUNET_GNSRECORD_TYPE_RECLAIM_TICKET != rd[i].record_type) | ||
1694 | continue; | ||
1695 | iter->cb (iter->cb_cls, (struct GNUNET_RECLAIM_Ticket *) rd[i].data); | ||
1696 | return; | ||
1697 | } | ||
1698 | GNUNET_NAMESTORE_zone_iterator_next (iter->ns_it, 1); | ||
1699 | } | ||
1700 | |||
1701 | |||
1702 | /** | ||
1703 | * Signal ticket iteration has finished | ||
1704 | * | ||
1705 | * @param cls handle to the iteration | ||
1706 | */ | ||
1707 | static void | ||
1708 | collect_tickets_finished_cb (void *cls) | ||
1709 | { | ||
1710 | struct RECLAIM_TICKETS_Iterator *iter = cls; | ||
1711 | |||
1712 | iter->ns_it = NULL; | ||
1713 | iter->cb (iter->cb_cls, NULL); | ||
1714 | cleanup_iter (iter); | ||
1715 | } | ||
1716 | |||
1717 | |||
1718 | /** | ||
1719 | * Cancel ticket iteration on namestore error | ||
1720 | * | ||
1721 | * @param cls the iteration handle | ||
1722 | */ | ||
1723 | static void | ||
1724 | collect_tickets_error_cb (void *cls) | ||
1725 | { | ||
1726 | struct RECLAIM_TICKETS_Iterator *iter = cls; | ||
1727 | |||
1728 | iter->ns_it = NULL; | ||
1729 | iter->cb (iter->cb_cls, NULL); | ||
1730 | cleanup_iter (iter); | ||
1731 | } | ||
1732 | |||
1733 | |||
1734 | /** | ||
1735 | * Continue ticket iteration | ||
1736 | * | ||
1737 | * @param iter the iteration to continue | ||
1738 | */ | ||
1739 | void | ||
1740 | RECLAIM_TICKETS_iteration_next (struct RECLAIM_TICKETS_Iterator *iter) | ||
1741 | { | ||
1742 | GNUNET_NAMESTORE_zone_iterator_next (iter->ns_it, 1); | ||
1743 | } | ||
1744 | |||
1745 | |||
1746 | /** | ||
1747 | * Stop a running ticket iteration | ||
1748 | * | ||
1749 | * @param iter iteration to cancel | ||
1750 | */ | ||
1751 | void | ||
1752 | RECLAIM_TICKETS_iteration_stop (struct RECLAIM_TICKETS_Iterator *iter) | ||
1753 | { | ||
1754 | GNUNET_NAMESTORE_zone_iteration_stop (iter->ns_it); | ||
1755 | cleanup_iter (iter); | ||
1756 | } | ||
1757 | |||
1758 | |||
1759 | /** | ||
1760 | * Iterate over all tickets issued by an identity | ||
1761 | * | ||
1762 | * @param identity the issuing identity | ||
1763 | * @param cb ticket callback function | ||
1764 | * @param cb_cls callback closure | ||
1765 | * @return a handle to the iteration | ||
1766 | */ | ||
1767 | struct RECLAIM_TICKETS_Iterator * | ||
1768 | RECLAIM_TICKETS_iteration_start ( | ||
1769 | const struct GNUNET_IDENTITY_PrivateKey *identity, | ||
1770 | RECLAIM_TICKETS_TicketIter cb, | ||
1771 | void *cb_cls) | ||
1772 | { | ||
1773 | struct RECLAIM_TICKETS_Iterator *iter; | ||
1774 | |||
1775 | iter = GNUNET_new (struct RECLAIM_TICKETS_Iterator); | ||
1776 | iter->cb = cb; | ||
1777 | iter->cb_cls = cb_cls; | ||
1778 | iter->ns_it = | ||
1779 | GNUNET_NAMESTORE_zone_iteration_start (nsh, | ||
1780 | identity, | ||
1781 | &collect_tickets_error_cb, | ||
1782 | iter, | ||
1783 | &collect_tickets_cb, | ||
1784 | iter, | ||
1785 | &collect_tickets_finished_cb, | ||
1786 | iter); | ||
1787 | return iter; | ||
1788 | } | ||
1789 | |||
1790 | |||
1791 | /** | ||
1792 | * Initialize tickets component | ||
1793 | * | ||
1794 | * @param c the configuration | ||
1795 | * @return GNUNET_SYSERR on error | ||
1796 | */ | ||
1797 | int | ||
1798 | RECLAIM_TICKETS_init (const struct GNUNET_CONFIGURATION_Handle *c) | ||
1799 | { | ||
1800 | // Get ticket expiration time (relative) from config | ||
1801 | if (GNUNET_OK == | ||
1802 | GNUNET_CONFIGURATION_get_value_time (c, | ||
1803 | "reclaim", | ||
1804 | "TICKET_REFRESH_INTERVAL", | ||
1805 | &ticket_refresh_interval)) | ||
1806 | { | ||
1807 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1808 | "Configured refresh interval for tickets: %s\n", | ||
1809 | GNUNET_STRINGS_relative_time_to_string (ticket_refresh_interval, | ||
1810 | GNUNET_YES)); | ||
1811 | } | ||
1812 | else | ||
1813 | { | ||
1814 | ticket_refresh_interval = DEFAULT_TICKET_REFRESH_INTERVAL; | ||
1815 | } | ||
1816 | // Connect to identity and namestore services | ||
1817 | nsh = GNUNET_NAMESTORE_connect (c); | ||
1818 | if (NULL == nsh) | ||
1819 | { | ||
1820 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, | ||
1821 | "error connecting to namestore"); | ||
1822 | return GNUNET_SYSERR; | ||
1823 | } | ||
1824 | gns = GNUNET_GNS_connect (c); | ||
1825 | if (NULL == gns) | ||
1826 | { | ||
1827 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "error connecting to gns"); | ||
1828 | return GNUNET_SYSERR; | ||
1829 | } | ||
1830 | stats = GNUNET_STATISTICS_create ("reclaim", c); | ||
1831 | return GNUNET_OK; | ||
1832 | } | ||
1833 | |||
1834 | |||
1835 | /** | ||
1836 | * Close handles and clean up. | ||
1837 | * FIXME: cancel all pending operations (gns, ns etc) | ||
1838 | */ | ||
1839 | void | ||
1840 | RECLAIM_TICKETS_deinit (void) | ||
1841 | { | ||
1842 | if (NULL != nsh) | ||
1843 | GNUNET_NAMESTORE_disconnect (nsh); | ||
1844 | nsh = NULL; | ||
1845 | if (NULL != gns) | ||
1846 | GNUNET_GNS_disconnect (gns); | ||
1847 | gns = NULL; | ||
1848 | if (NULL != stats) | ||
1849 | { | ||
1850 | GNUNET_STATISTICS_destroy (stats, GNUNET_NO); | ||
1851 | stats = NULL; | ||
1852 | } | ||
1853 | } | ||