aboutsummaryrefslogtreecommitdiff
path: root/src/revocation
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2013-11-19 19:46:30 +0000
committerChristian Grothoff <christian@grothoff.org>2013-11-19 19:46:30 +0000
commitf93a17240ae3e809ff6ef84af917c600306df3ff (patch)
tree830fa595e5e6218c5285b8b3fc249bded2ac1bb9 /src/revocation
parent332160659373044ac0c2a15a799a55cf7d113ee9 (diff)
downloadgnunet-f93a17240ae3e809ff6ef84af917c600306df3ff.tar.gz
gnunet-f93a17240ae3e809ff6ef84af917c600306df3ff.zip
-implementing revocation set union
Diffstat (limited to 'src/revocation')
-rw-r--r--src/revocation/gnunet-service-revocation.c229
1 files changed, 213 insertions, 16 deletions
diff --git a/src/revocation/gnunet-service-revocation.c b/src/revocation/gnunet-service-revocation.c
index 5a7170de6..11f3fab77 100644
--- a/src/revocation/gnunet-service-revocation.c
+++ b/src/revocation/gnunet-service-revocation.c
@@ -31,7 +31,6 @@
31 * peers that connect. 31 * peers that connect.
32 * 32 *
33 * TODO: 33 * TODO:
34 * - handle p2p connect (trigger SET union, #3057)
35 * - optimization: avoid sending revocation back to peer that we got it from; 34 * - optimization: avoid sending revocation back to peer that we got it from;
36 * - optimization: have randomized delay in sending revocations to other peers 35 * - optimization: have randomized delay in sending revocations to other peers
37 * to make it rare to traverse each link twice (NSE-style) 36 * to make it rare to traverse each link twice (NSE-style)
@@ -66,6 +65,16 @@ struct PeerEntry
66 */ 65 */
67 struct GNUNET_PeerIdentity id; 66 struct GNUNET_PeerIdentity id;
68 67
68 /**
69 * Tasked used to trigger the set union operation.
70 */
71 GNUNET_SCHEDULER_TaskIdentifier transmit_task;
72
73 /**
74 * Handle to active set union operation (over revocation sets).
75 */
76 struct GNUNET_SET_OperationHandle *so;
77
69}; 78};
70 79
71 80
@@ -121,10 +130,22 @@ static struct GNUNET_SERVER_NotificationContext *nc;
121static struct GNUNET_DISK_FileHandle *revocation_db; 130static struct GNUNET_DISK_FileHandle *revocation_db;
122 131
123/** 132/**
133 * Handle for us listening to incoming revocation set union requests.
134 */
135static struct GNUNET_SET_ListenHandle *revocation_union_listen_handle;
136
137/**
124 * Amount of work required (W-bit collisions) for REVOCATION proofs, in collision-bits. 138 * Amount of work required (W-bit collisions) for REVOCATION proofs, in collision-bits.
125 */ 139 */
126static unsigned long long revocation_work_required; 140static unsigned long long revocation_work_required;
127 141
142/**
143 * Our application ID for set union operations. Must be the
144 * same for all (compatible) peers.
145 */
146static struct GNUNET_HashCode revocation_set_union_app_id;
147
148
128 149
129/** 150/**
130 * An revoke message has been received, check that it is well-formed. 151 * An revoke message has been received, check that it is well-formed.
@@ -360,6 +381,105 @@ handle_p2p_revoke_message (void *cls,
360} 381}
361 382
362 383
384
385/**
386 * Callback for set operation results. Called for each element in the
387 * result set. Each element contains a revocation, which we should
388 * validate and then add to our revocation list (and set).
389 *
390 * @param cls closure
391 * @param element a result element, only valid if status is #GNUNET_SET_STATUS_OK
392 * @param status see `enum GNUNET_SET_Status`
393 */
394static void
395add_revocation (void *cls,
396 const struct GNUNET_SET_Element *element,
397 enum GNUNET_SET_Status status)
398{
399 struct PeerEntry *peer_entry = cls;
400 const struct RevokeMessage *rm;
401
402 switch (status)
403 {
404 case GNUNET_SET_STATUS_OK:
405 if (element->size != sizeof (struct RevokeMessage))
406 {
407 GNUNET_break_op (0);
408 return;
409 }
410 if (0 != element->type)
411 {
412 GNUNET_STATISTICS_update (stats,
413 "# unsupported revocations received via set union",
414 1, GNUNET_NO);
415 return;
416 }
417 rm = element->data;
418 (void) handle_p2p_revoke_message (NULL,
419 &peer_entry->id,
420 &rm->header);
421 GNUNET_STATISTICS_update (stats,
422 "# revocation messages received via set union",
423 1, GNUNET_NO);
424 break;
425 case GNUNET_SET_STATUS_TIMEOUT:
426 case GNUNET_SET_STATUS_FAILURE:
427 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
428 _("Error computing revocation set union with %s\n"),
429 GNUNET_i2s (&peer_entry->id));
430 peer_entry->so = NULL;
431 GNUNET_STATISTICS_update (stats, "# revocation set unions failed",
432 1, GNUNET_NO);
433 break;
434 case GNUNET_SET_STATUS_HALF_DONE:
435 break;
436 case GNUNET_SET_STATUS_DONE:
437 peer_entry->so = NULL;
438 GNUNET_STATISTICS_update (stats, "# revocation set unions completed",
439 1, GNUNET_NO);
440 break;
441 default:
442 GNUNET_break (0);
443 break;
444 }
445}
446
447
448/**
449 * The timeout for performing the set union has expired,
450 * run the set operation on the revocation certificates.
451 *
452 * @param cls NULL
453 * @param tc scheduler context (unused)
454 */
455static void
456transmit_task_cb (void *cls,
457 const struct GNUNET_SCHEDULER_TaskContext *tc)
458{
459 struct PeerEntry *peer_entry = cls;
460 uint16_t salt;
461
462 salt = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
463 UINT16_MAX);
464 peer_entry->transmit_task = GNUNET_SCHEDULER_NO_TASK;
465 peer_entry->so = GNUNET_SET_prepare (&peer_entry->id,
466 &revocation_set_union_app_id,
467 NULL, salt,
468 GNUNET_SET_RESULT_ADDED,
469 &add_revocation,
470 peer_entry);
471 if (GNUNET_OK !=
472 GNUNET_SET_commit (peer_entry->so,
473 revocation_set))
474 {
475 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
476 _("SET service crashed, terminating revocation service\n"));
477 GNUNET_SCHEDULER_shutdown ();
478 return;
479 }
480}
481
482
363/** 483/**
364 * Method called whenever a peer connects. Sets up the PeerEntry and 484 * Method called whenever a peer connects. Sets up the PeerEntry and
365 * schedules the initial revocation set exchange with this peer. 485 * schedules the initial revocation set exchange with this peer.
@@ -372,22 +492,38 @@ handle_core_connect (void *cls,
372 const struct GNUNET_PeerIdentity *peer) 492 const struct GNUNET_PeerIdentity *peer)
373{ 493{
374 struct PeerEntry *peer_entry; 494 struct PeerEntry *peer_entry;
495 struct GNUNET_HashCode my_hash;
496 struct GNUNET_HashCode peer_hash;
375 497
376 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%s' connected to us\n", 498 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
499 "Peer `%s' connected to us\n",
377 GNUNET_i2s (peer)); 500 GNUNET_i2s (peer));
378 peer_entry = GNUNET_new (struct PeerEntry); 501 peer_entry = GNUNET_CONTAINER_multipeermap_get (peers,
379 peer_entry->id = *peer; 502 peer);
503 if (NULL == peer_entry)
504 {
505 peer_entry = GNUNET_new (struct PeerEntry);
506 peer_entry->id = *peer;
507 GNUNET_assert (GNUNET_OK ==
508 GNUNET_CONTAINER_multipeermap_put (peers, peer,
509 peer_entry,
510 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
511 }
512 else
513 {
514 GNUNET_assert (NULL == peer_entry->mq);
515 }
380 peer_entry->mq = GNUNET_CORE_mq_create (core_api, peer); 516 peer_entry->mq = GNUNET_CORE_mq_create (core_api, peer);
381 GNUNET_assert (GNUNET_OK == 517 GNUNET_CRYPTO_hash (&my_identity, sizeof (my_identity), &my_hash);
382 GNUNET_CONTAINER_multipeermap_put (peers, peer, 518 GNUNET_CRYPTO_hash (peer, sizeof (*peer), &peer_hash);
383 peer_entry, 519 if (0 < GNUNET_CRYPTO_hash_cmp (&my_hash,
384 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); 520 &peer_hash))
385 // GNUNET_break (0); // FIXME: implement revocation set union on connect! 521 {
386#if 0 522 peer_entry->transmit_task =
387 peer_entry->transmit_task = 523 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
388 GNUNET_SCHEDULER_add_delayed (get_transmit_delay (-1), &transmit_task_cb, 524 &transmit_task_cb,
389 peer_entry); 525 peer_entry);
390#endif 526 }
391 GNUNET_STATISTICS_update (stats, "# peers connected", 1, GNUNET_NO); 527 GNUNET_STATISTICS_update (stats, "# peers connected", 1, GNUNET_NO);
392} 528}
393 529
@@ -418,13 +554,16 @@ handle_core_disconnect (void *cls,
418 GNUNET_CONTAINER_multipeermap_remove (peers, peer, 554 GNUNET_CONTAINER_multipeermap_remove (peers, peer,
419 pos)); 555 pos));
420 GNUNET_MQ_destroy (pos->mq); 556 GNUNET_MQ_destroy (pos->mq);
421#if 0
422 if (pos->transmit_task != GNUNET_SCHEDULER_NO_TASK) 557 if (pos->transmit_task != GNUNET_SCHEDULER_NO_TASK)
423 { 558 {
424 GNUNET_SCHEDULER_cancel (pos->transmit_task); 559 GNUNET_SCHEDULER_cancel (pos->transmit_task);
425 pos->transmit_task = GNUNET_SCHEDULER_NO_TASK; 560 pos->transmit_task = GNUNET_SCHEDULER_NO_TASK;
426 } 561 }
427#endif 562 if (NULL != pos->so)
563 {
564 GNUNET_SET_operation_cancel (pos->so);
565 pos->so = NULL;
566 }
428 GNUNET_free (pos); 567 GNUNET_free (pos);
429 GNUNET_STATISTICS_update (stats, "# peers connected", -1, GNUNET_NO); 568 GNUNET_STATISTICS_update (stats, "# peers connected", -1, GNUNET_NO);
430} 569}
@@ -463,6 +602,11 @@ shutdown_task (void *cls,
463 GNUNET_SET_destroy (revocation_set); 602 GNUNET_SET_destroy (revocation_set);
464 revocation_set = NULL; 603 revocation_set = NULL;
465 } 604 }
605 if (NULL != revocation_union_listen_handle)
606 {
607 GNUNET_SET_listen_cancel (revocation_union_listen_handle);
608 revocation_union_listen_handle = NULL;
609 }
466 if (NULL != core_api) 610 if (NULL != core_api)
467 { 611 {
468 GNUNET_CORE_disconnect (core_api); 612 GNUNET_CORE_disconnect (core_api);
@@ -517,6 +661,52 @@ core_init (void *cls,
517 661
518 662
519/** 663/**
664 * Called when another peer wants to do a set operation with the
665 * local peer. If a listen error occurs, the 'request' is NULL.
666 *
667 * @param cls closure
668 * @param other_peer the other peer
669 * @param context_msg message with application specific information from
670 * the other peer
671 * @param request request from the other peer (never NULL), use GNUNET_SET_accept()
672 * to accept it, otherwise the request will be refused
673 * Note that we can't just return value from the listen callback,
674 * as it is also necessary to specify the set we want to do the
675 * operation with, whith sometimes can be derived from the context
676 * message. It's necessary to specify the timeout.
677 */
678static void
679handle_revocation_union_request (void *cls,
680 const struct GNUNET_PeerIdentity *other_peer,
681 const struct GNUNET_MessageHeader *context_msg,
682 struct GNUNET_SET_Request *request)
683{
684 struct PeerEntry *peer_entry;
685
686 if (NULL == request)
687 {
688 GNUNET_break (0);
689 return;
690 }
691 peer_entry = GNUNET_CONTAINER_multipeermap_get (peers,
692 other_peer);
693 if (NULL == peer_entry)
694 {
695 peer_entry = GNUNET_new (struct PeerEntry);
696 peer_entry->id = *other_peer;
697 GNUNET_assert (GNUNET_OK ==
698 GNUNET_CONTAINER_multipeermap_put (peers, other_peer,
699 peer_entry,
700 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
701 }
702 peer_entry->so = GNUNET_SET_accept (request,
703 GNUNET_SET_RESULT_ADDED,
704 &add_revocation,
705 peer_entry);
706}
707
708
709/**
520 * Handle network size estimate clients. 710 * Handle network size estimate clients.
521 * 711 *
522 * @param cls closure 712 * @param cls closure
@@ -584,7 +774,11 @@ run (void *cls,
584 } 774 }
585 revocation_set = GNUNET_SET_create (cfg, 775 revocation_set = GNUNET_SET_create (cfg,
586 GNUNET_SET_OPERATION_UNION); 776 GNUNET_SET_OPERATION_UNION);
587 777 revocation_union_listen_handle = GNUNET_SET_listen (cfg,
778 GNUNET_SET_OPERATION_UNION,
779 &revocation_set_union_app_id,
780 &handle_revocation_union_request,
781 NULL);
588 revocation_db = GNUNET_DISK_file_open (fn, 782 revocation_db = GNUNET_DISK_file_open (fn,
589 GNUNET_DISK_OPEN_READWRITE | 783 GNUNET_DISK_OPEN_READWRITE |
590 GNUNET_DISK_OPEN_CREATE, 784 GNUNET_DISK_OPEN_CREATE,
@@ -667,6 +861,9 @@ int
667main (int argc, 861main (int argc,
668 char *const *argv) 862 char *const *argv)
669{ 863{
864 GNUNET_CRYPTO_hash ("revocation-set-union-application-id",
865 strlen ("revocation-set-union-application-id"),
866 &revocation_set_union_app_id);
670 return (GNUNET_OK == 867 return (GNUNET_OK ==
671 GNUNET_SERVICE_run (argc, argv, "revocation", GNUNET_SERVICE_OPTION_NONE, 868 GNUNET_SERVICE_run (argc, argv, "revocation", GNUNET_SERVICE_OPTION_NONE,
672 &run, NULL)) ? 0 : 1; 869 &run, NULL)) ? 0 : 1;