X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Frevocation%2Fgnunet-service-revocation.c;h=9d077f874dd3e7176cefcc9ba9a5105f0856e5f4;hb=5031ce9079f9e5292468374fa8d4a95462e7168a;hp=c4622279acccf0d9b736998b94ea032b25b06ff6;hpb=69cf4d54ba9defa69830d4be84c01940bfb9fe28;p=oweals%2Fgnunet.git diff --git a/src/revocation/gnunet-service-revocation.c b/src/revocation/gnunet-service-revocation.c index c4622279a..9d077f874 100644 --- a/src/revocation/gnunet-service-revocation.c +++ b/src/revocation/gnunet-service-revocation.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2013 Christian Grothoff (and other contributing authors) + Copyright (C) 2013, 2014, 2016 GNUnet e.V. GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public Licerevocation as published @@ -14,8 +14,8 @@ You should have received a copy of the GNU General Public Licerevocation along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ /** @@ -31,15 +31,14 @@ * peers that connect. * * TODO: - * - broadcast p2p revocations - * - handle p2p connect (trigger SET union) * - optimization: avoid sending revocation back to peer that we got it from; - * - optimization: have randomized delay in sending revocations to other peers + * - optimization: have randomized delay in sending revocations to other peers * to make it rare to traverse each link twice (NSE-style) */ #include "platform.h" #include #include "gnunet_util_lib.h" +#include "gnunet_block_lib.h" #include "gnunet_constants.h" #include "gnunet_protocols.h" #include "gnunet_signatures.h" @@ -58,9 +57,9 @@ struct PeerEntry { /** - * Core handle for sending messages to this peer. + * Queue for sending messages to this peer. */ - struct GNUNET_CORE_TransmitHandle *th; + struct GNUNET_MQ_Handle *mq; /** * What is the identity of the peer? @@ -68,9 +67,14 @@ struct PeerEntry struct GNUNET_PeerIdentity id; /** - * Task scheduled to send message to this peer. + * Tasked used to trigger the set union operation. */ - GNUNET_SCHEDULER_TaskIdentifier transmit_task; + struct GNUNET_SCHEDULER_Task *transmit_task; + + /** + * Handle to active set union operation (over revocation sets). + */ + struct GNUNET_SET_OperationHandle *so; }; @@ -83,7 +87,7 @@ static struct GNUNET_SET_Handle *revocation_set; /** * Hash map with all revoked keys, maps the hash of the public key * to the respective `struct RevokeMessage`. - */ + */ static struct GNUNET_CONTAINER_MultiHashMap *revocation_map; /** @@ -99,7 +103,7 @@ static struct GNUNET_STATISTICS_Handle *stats; /** * Handle to the core service (for flooding) */ -static struct GNUNET_CORE_Handle *coreAPI; +static struct GNUNET_CORE_Handle *core_api; /** * Map of all connected peers. @@ -112,24 +116,47 @@ static struct GNUNET_CONTAINER_MultiPeerMap *peers; static struct GNUNET_PeerIdentity my_identity; /** - * Handle to this serivce's server. + * File handle for the revocation database. */ -static struct GNUNET_SERVER_Handle *srv; +static struct GNUNET_DISK_FileHandle *revocation_db; /** - * Notification context for convenient sending of replies to the clients. + * Handle for us listening to incoming revocation set union requests. */ -static struct GNUNET_SERVER_NotificationContext *nc; +static struct GNUNET_SET_ListenHandle *revocation_union_listen_handle; /** - * File handle for the revocation database. + * Amount of work required (W-bit collisions) for REVOCATION proofs, in collision-bits. */ -static struct GNUNET_DISK_FileHandle *revocation_db; +static unsigned long long revocation_work_required; /** - * Amount of work required (W-bit collisions) for REVOCATION proofs, in collision-bits. + * Our application ID for set union operations. Must be the + * same for all (compatible) peers. */ -static unsigned long long revocation_work_required; +static struct GNUNET_HashCode revocation_set_union_app_id; + + +/** + * Create a new PeerEntry and add it to the peers multipeermap. + * + * @param peer the peer identity + * @return a pointer to the new PeerEntry + */ +static struct PeerEntry * +new_peer_entry(const struct GNUNET_PeerIdentity *peer) +{ + struct PeerEntry *peer_entry; + + peer_entry = GNUNET_new (struct PeerEntry); + peer_entry->id = *peer; + GNUNET_assert (GNUNET_OK == + GNUNET_CONTAINER_multipeermap_put (peers, + &peer_entry->id, + peer_entry, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); + return peer_entry; +} /** @@ -147,15 +174,13 @@ verify_revoke_message (const struct RevokeMessage *rm) rm->proof_of_work, (unsigned int) revocation_work_required)) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Proof of work invalid: %llu!\n", - (unsigned long long) - GNUNET_ntohll (rm->proof_of_work)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Proof of work invalid!\n"); GNUNET_break_op (0); return GNUNET_NO; } if (GNUNET_OK != - GNUNET_CRYPTO_ecc_verify (GNUNET_SIGNATURE_PURPOSE_REVOCATION, + GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_REVOCATION, &rm->purpose, &rm->signature, &rm->public_key)) @@ -167,42 +192,71 @@ verify_revoke_message (const struct RevokeMessage *rm) } +/** + * Handle client connecting to the service. + * + * @param cls NULL + * @param client the new client + * @param mq the message queue of @a client + * @return @a client + */ +static void * +client_connect_cb (void *cls, + struct GNUNET_SERVICE_Client *client, + struct GNUNET_MQ_Handle *mq) +{ + return client; +} + + +/** + * Handle client connecting to the service. + * + * @param cls NULL + * @param client the new client + * @param app_cls must alias @a client + */ +static void +client_disconnect_cb (void *cls, + struct GNUNET_SERVICE_Client *client, + void *app_cls) +{ + GNUNET_assert (client == app_cls); +} + + /** * Handle QUERY message from client. * - * @param cls unused - * @param client who sent the message - * @param message the message received + * @param cls client who sent the message + * @param qm the message received */ static void -handle_query_message (void *cls, - struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) +handle_query_message (void *cls, + const struct QueryMessage *qm) { - const struct QueryMessage *qm = (const struct QueryMessage *) message; - struct QueryResponseMessage qrm; + struct GNUNET_SERVICE_Client *client = cls; + struct GNUNET_MQ_Envelope *env; + struct QueryResponseMessage *qrm; struct GNUNET_HashCode hc; int res; GNUNET_CRYPTO_hash (&qm->key, - sizeof (struct GNUNET_CRYPTO_EccPublicSignKey), + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), &hc); - res = GNUNET_CONTAINER_multihashmap_contains (revocation_map, &hc); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - (GNUNET_NO == res) + res = GNUNET_CONTAINER_multihashmap_contains (revocation_map, + &hc); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + (GNUNET_NO == res) ? "Received revocation check for valid key `%s' from client\n" : "Received revocation check for revoked key `%s' from client\n", GNUNET_h2s (&hc)); - qrm.header.size = htons (sizeof (struct QueryResponseMessage)); - qrm.header.type = htons (GNUNET_MESSAGE_TYPE_REVOCATION_QUERY_RESPONSE); - qrm.is_valid = htons ((GNUNET_YES == res) ? GNUNET_NO : GNUNET_YES); - GNUNET_SERVER_notification_context_add (nc, - client); - GNUNET_SERVER_notification_context_unicast (nc, - client, - &qrm.header, - GNUNET_NO); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + env = GNUNET_MQ_msg (qrm, + GNUNET_MESSAGE_TYPE_REVOCATION_QUERY_RESPONSE); + qrm->is_valid = htonl ((GNUNET_YES == res) ? GNUNET_NO : GNUNET_YES); + GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), + env); + GNUNET_SERVICE_client_continue (client); } @@ -219,7 +273,23 @@ do_flood (void *cls, const struct GNUNET_PeerIdentity *target, void *value) { - GNUNET_break (0); // FIXME: not implemented + const struct RevokeMessage *rm = cls; + struct PeerEntry *pe = value; + struct GNUNET_MQ_Envelope *e; + struct RevokeMessage *cp; + + if (NULL == pe->mq) + return GNUNET_OK; /* peer connected to us via SET, + but we have no direct CORE + connection for flooding */ + e = GNUNET_MQ_msg (cp, + GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE); + *cp = *rm; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Flooding revocation to `%s'\n", + GNUNET_i2s (target)); + GNUNET_MQ_send (pe->mq, + e); return GNUNET_OK; } @@ -228,7 +298,7 @@ do_flood (void *cls, * Publicize revocation message. Stores the message locally in the * database and passes it to all connected neighbours (and adds it to * the set for future connections). - * + * * @param rm message to publicize * @return #GNUNET_OK on success, #GNUNET_NO if we encountered an error, * #GNUNET_SYSERR if the message was malformed @@ -241,22 +311,22 @@ publicize_rm (const struct RevokeMessage *rm) struct GNUNET_SET_Element e; GNUNET_CRYPTO_hash (&rm->public_key, - sizeof (struct GNUNET_CRYPTO_EccPublicSignKey), + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), &hc); if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (revocation_map, &hc)) { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("Duplicate revocation received from peer. Ignored.\n")); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Duplicate revocation received from peer. Ignored.\n"); return GNUNET_OK; } - if (GNUNET_OK != + if (GNUNET_OK != verify_revoke_message (rm)) { GNUNET_break_op (0); return GNUNET_SYSERR; - } + } /* write to disk */ if (sizeof (struct RevokeMessage) != GNUNET_DISK_file_write (revocation_db, @@ -283,18 +353,24 @@ publicize_rm (const struct RevokeMessage *rm) GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); /* add to set for future connections */ e.size = htons (rm->header.size); - e.type = 0; + e.element_type = GNUNET_BLOCK_TYPE_REVOCATION; e.data = rm; if (GNUNET_OK != GNUNET_SET_add_element (revocation_set, &e, - NULL, NULL)) + NULL, + NULL)) { GNUNET_break (0); return GNUNET_OK; } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Added revocation info to SET\n"); + } /* flood to neighbours */ - GNUNET_CONTAINER_multipeermap_iterate (peers, + GNUNET_CONTAINER_multipeermap_iterate (peers, &do_flood, cp); return GNUNET_OK; @@ -304,38 +380,32 @@ publicize_rm (const struct RevokeMessage *rm) /** * Handle REVOKE message from client. * - * @param cls unused - * @param client who sent the message - * @param message the message received + * @param cls client who sent the message + * @param rm the message received */ static void -handle_revoke_message (void *cls, - struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) +handle_revoke_message (void *cls, + const struct RevokeMessage *rm) { - const struct RevokeMessage *rm; - struct RevocationResponseMessage rrm; + struct GNUNET_SERVICE_Client *client = cls; + struct GNUNET_MQ_Envelope *env; + struct RevocationResponseMessage *rrm; int ret; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received REVOKE message from client\n"); - rm = (const struct RevokeMessage *) message; if (GNUNET_SYSERR == (ret = publicize_rm (rm))) { GNUNET_break_op (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + GNUNET_SERVICE_client_drop (client); return; } - rrm.header.size = htons (sizeof (struct RevocationResponseMessage)); - rrm.header.type = htons (GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE_RESPONSE); - rrm.is_valid = htons ((GNUNET_OK == ret) ? GNUNET_NO : GNUNET_YES); - GNUNET_SERVER_notification_context_add (nc, - client); - GNUNET_SERVER_notification_context_unicast (nc, - client, - &rrm.header, - GNUNET_NO); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + env = GNUNET_MQ_msg (rrm, + GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE_RESPONSE); + rrm->is_valid = htonl ((GNUNET_OK == ret) ? GNUNET_NO : GNUNET_YES); + GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), + env); + GNUNET_SERVICE_client_continue (client); } @@ -343,21 +413,118 @@ handle_revoke_message (void *cls, * Core handler for flooded revocation messages. * * @param cls closure unused - * @param message message - * @param peer peer identity this message is from (ignored) + * @param rm revocation message */ -static int -handle_p2p_revoke_message (void *cls, - const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_MessageHeader *message) +static void +handle_p2p_revoke (void *cls, + const struct RevokeMessage *rm) { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received REVOKE message\n"); + GNUNET_break_op (GNUNET_SYSERR != + publicize_rm (rm)); +} + + +/** + * Callback for set operation results. Called for each element in the + * result set. Each element contains a revocation, which we should + * validate and then add to our revocation list (and set). + * + * @param cls closure + * @param element a result element, only valid if status is #GNUNET_SET_STATUS_OK + * @param current_size current set size + * @param status see `enum GNUNET_SET_Status` + */ +static void +add_revocation (void *cls, + const struct GNUNET_SET_Element *element, + uint64_t current_size, + enum GNUNET_SET_Status status) +{ + struct PeerEntry *peer_entry = cls; const struct RevokeMessage *rm; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Received REVOKE message from peer\n"); - rm = (const struct RevokeMessage *) message; - GNUNET_break_op (GNUNET_SYSERR != publicize_rm (rm)); - return GNUNET_OK; + switch (status) + { + case GNUNET_SET_STATUS_OK: + if (element->size != sizeof (struct RevokeMessage)) + { + GNUNET_break_op (0); + return; + } + if (GNUNET_BLOCK_TYPE_REVOCATION != element->element_type) + { + GNUNET_STATISTICS_update (stats, + gettext_noop ("# unsupported revocations received via set union"), + 1, + GNUNET_NO); + return; + } + rm = element->data; + (void) handle_p2p_revoke (NULL, + rm); + GNUNET_STATISTICS_update (stats, + gettext_noop ("# revocation messages received via set union"), + 1, GNUNET_NO); + break; + case GNUNET_SET_STATUS_FAILURE: + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("Error computing revocation set union with %s\n"), + GNUNET_i2s (&peer_entry->id)); + peer_entry->so = NULL; + GNUNET_STATISTICS_update (stats, + gettext_noop ("# revocation set unions failed"), + 1, + GNUNET_NO); + break; + case GNUNET_SET_STATUS_HALF_DONE: + break; + case GNUNET_SET_STATUS_DONE: + peer_entry->so = NULL; + GNUNET_STATISTICS_update (stats, + gettext_noop ("# revocation set unions completed"), + 1, + GNUNET_NO); + break; + default: + GNUNET_break (0); + break; + } +} + + +/** + * The timeout for performing the set union has expired, + * run the set operation on the revocation certificates. + * + * @param cls NULL + */ +static void +transmit_task_cb (void *cls) +{ + struct PeerEntry *peer_entry = cls; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Starting set exchange with peer `%s'\n", + GNUNET_i2s (&peer_entry->id)); + peer_entry->transmit_task = NULL; + peer_entry->so = GNUNET_SET_prepare (&peer_entry->id, + &revocation_set_union_app_id, + NULL, + GNUNET_SET_RESULT_ADDED, + (struct GNUNET_SET_Option[]) {{ 0 }}, + &add_revocation, + peer_entry); + if (GNUNET_OK != + GNUNET_SET_commit (peer_entry->so, + revocation_set)) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("SET service crashed, terminating revocation service\n")); + GNUNET_SCHEDULER_shutdown (); + return; + } } @@ -368,27 +535,60 @@ handle_p2p_revoke_message (void *cls, * @param cls closure * @param peer peer identity this notification is about */ -static void +static void * handle_core_connect (void *cls, - const struct GNUNET_PeerIdentity *peer) + const struct GNUNET_PeerIdentity *peer, + struct GNUNET_MQ_Handle *mq) { struct PeerEntry *peer_entry; + struct GNUNET_HashCode my_hash; + struct GNUNET_HashCode peer_hash; + + if (0 == memcmp (peer, + &my_identity, + sizeof (my_identity))) + { + return NULL; + } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%s' connected to us\n", + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Peer `%s' connected to us\n", GNUNET_i2s (peer)); - peer_entry = GNUNET_new (struct PeerEntry); - peer_entry->id = *peer; - GNUNET_assert (GNUNET_OK == - GNUNET_CONTAINER_multipeermap_put (peers, peer, - peer_entry, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); - GNUNET_break (0); // FIXME: implement revocation set union on connect! -#if 0 - peer_entry->transmit_task = - GNUNET_SCHEDULER_add_delayed (get_transmit_delay (-1), &transmit_task_cb, + GNUNET_STATISTICS_update (stats, + "# peers connected", + 1, + GNUNET_NO); + peer_entry = GNUNET_CONTAINER_multipeermap_get (peers, + peer); + if (NULL != peer_entry) + { + /* This can happen if "core"'s notification is a tad late + and CADET+SET were faster and already produced a + #handle_revocation_union_request() for us to deal + with. This should be rare, but isn't impossible. */ + peer_entry->mq = mq; + return peer_entry; + } + peer_entry = new_peer_entry (peer); + peer_entry->mq = mq; + GNUNET_CRYPTO_hash (&my_identity, + sizeof (my_identity), + &my_hash); + GNUNET_CRYPTO_hash (peer, + sizeof (*peer), + &peer_hash); + if (0 < GNUNET_CRYPTO_hash_cmp (&my_hash, + &peer_hash)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Starting SET operation with peer `%s'\n", + GNUNET_i2s (peer)); + peer_entry->transmit_task = + GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, + &transmit_task_cb, peer_entry); -#endif - GNUNET_STATISTICS_update (stats, "# peers connected", 1, GNUNET_NO); + } + return peer_entry; } @@ -398,45 +598,48 @@ handle_core_connect (void *cls, * * @param cls closure * @param peer peer identity this notification is about + * @param internal_cls our `struct PeerEntry` for this peer */ static void -handle_core_disconnect (void *cls, - const struct GNUNET_PeerIdentity *peer) +handle_core_disconnect (void *cls, + const struct GNUNET_PeerIdentity *peer, + void *internal_cls) { - struct PeerEntry *pos; + struct PeerEntry *peer_entry = internal_cls; + if (0 == memcmp (peer, + &my_identity, + sizeof (my_identity))) + return; + GNUNET_assert (NULL != peer_entry); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%s' disconnected from us\n", GNUNET_i2s (peer)); - pos = GNUNET_CONTAINER_multipeermap_get (peers, peer); - if (NULL == pos) - { - GNUNET_break (0); - return; - } GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multipeermap_remove (peers, peer, - pos)); -#if 0 - if (pos->transmit_task != GNUNET_SCHEDULER_NO_TASK) + GNUNET_CONTAINER_multipeermap_remove (peers, + peer, + peer_entry)); + if (NULL != peer_entry->transmit_task) { - GNUNET_SCHEDULER_cancel (pos->transmit_task); - pos->transmit_task = GNUNET_SCHEDULER_NO_TASK; + GNUNET_SCHEDULER_cancel (peer_entry->transmit_task); + peer_entry->transmit_task = NULL; } - if (NULL != pos->th) + if (NULL != peer_entry->so) { - GNUNET_CORE_notify_transmit_ready_cancel (pos->th); - pos->th = NULL; + GNUNET_SET_operation_cancel (peer_entry->so); + peer_entry->so = NULL; } -#endif - GNUNET_free (pos); - GNUNET_STATISTICS_update (stats, "# peers connected", -1, GNUNET_NO); + GNUNET_free (peer_entry); + GNUNET_STATISTICS_update (stats, + "# peers connected", + -1, + GNUNET_NO); } /** * Free all values in a hash map. - * + * * @param cls NULL * @param key the key * @param value value to free @@ -456,21 +659,24 @@ free_entry (void *cls, * Task run during shutdown. * * @param cls unused - * @param tc unused */ static void -shutdown_task (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) +shutdown_task (void *cls) { if (NULL != revocation_set) { GNUNET_SET_destroy (revocation_set); revocation_set = NULL; } - if (NULL != coreAPI) + if (NULL != revocation_union_listen_handle) + { + GNUNET_SET_listen_cancel (revocation_union_listen_handle); + revocation_union_listen_handle = NULL; + } + if (NULL != core_api) { - GNUNET_CORE_disconnect (coreAPI); - coreAPI = NULL; + GNUNET_CORE_disconnect (core_api); + core_api = NULL; } if (NULL != stats) { @@ -482,11 +688,6 @@ shutdown_task (void *cls, GNUNET_CONTAINER_multipeermap_destroy (peers); peers = NULL; } - if (NULL != nc) - { - GNUNET_SERVER_notification_context_destroy (nc); - nc = NULL; - } if (NULL != revocation_db) { GNUNET_DISK_file_close (revocation_db); @@ -506,12 +707,12 @@ shutdown_task (void *cls, * @param identity the public identity of this peer */ static void -core_init (void *cls, +core_init (void *cls, const struct GNUNET_PeerIdentity *identity) { if (NULL == identity) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Connection to core FAILED!\n"); GNUNET_SCHEDULER_shutdown (); return; @@ -520,6 +721,60 @@ core_init (void *cls, } +/** + * Called when another peer wants to do a set operation with the + * local peer. If a listen error occurs, the 'request' is NULL. + * + * @param cls closure + * @param other_peer the other peer + * @param context_msg message with application specific information from + * the other peer + * @param request request from the other peer (never NULL), use GNUNET_SET_accept() + * to accept it, otherwise the request will be refused + * Note that we can't just return value from the listen callback, + * as it is also necessary to specify the set we want to do the + * operation with, whith sometimes can be derived from the context + * message. It's necessary to specify the timeout. + */ +static void +handle_revocation_union_request (void *cls, + const struct GNUNET_PeerIdentity *other_peer, + const struct GNUNET_MessageHeader *context_msg, + struct GNUNET_SET_Request *request) +{ + struct PeerEntry *peer_entry; + + if (NULL == request) + { + GNUNET_break (0); + return; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received set exchange request from peer `%s'\n", + GNUNET_i2s (other_peer)); + peer_entry = GNUNET_CONTAINER_multipeermap_get (peers, + other_peer); + if (NULL == peer_entry) + { + peer_entry = new_peer_entry (other_peer); + } + peer_entry->so = GNUNET_SET_accept (request, + GNUNET_SET_RESULT_ADDED, + (struct GNUNET_SET_Option[]) {{ 0 }}, + &add_revocation, + peer_entry); + if (GNUNET_OK != + GNUNET_SET_commit (peer_entry->so, + revocation_set)) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("SET service crashed, terminating revocation service\n")); + GNUNET_SCHEDULER_shutdown (); + return; + } +} + + /** * Handle network size estimate clients. * @@ -528,27 +783,25 @@ core_init (void *cls, * @param c configuration to use */ static void -run (void *cls, - struct GNUNET_SERVER_Handle *server, - const struct GNUNET_CONFIGURATION_Handle *c) +run (void *cls, + const struct GNUNET_CONFIGURATION_Handle *c, + struct GNUNET_SERVICE_Handle *service) { - static const struct GNUNET_SERVER_MessageHandler handlers[] = { - {&handle_query_message, NULL, GNUNET_MESSAGE_TYPE_REVOCATION_QUERY, - sizeof (struct QueryMessage)}, - {&handle_revoke_message, NULL, GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE, - sizeof (struct RevokeMessage)}, - {NULL, NULL, 0, 0} - }; - static const struct GNUNET_CORE_MessageHandler core_handlers[] = { - {&handle_p2p_revoke_message, GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE, - sizeof (struct RevokeMessage)}, - {NULL, 0, 0} + struct GNUNET_MQ_MessageHandler core_handlers[] = { + GNUNET_MQ_hd_fixed_size (p2p_revoke, + GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE, + struct RevokeMessage, + NULL), + GNUNET_MQ_handler_end () }; char *fn; uint64_t left; struct RevokeMessage *rm; struct GNUNET_HashCode hc; + GNUNET_CRYPTO_hash ("revocation-set-union-application-id", + strlen ("revocation-set-union-application-id"), + &revocation_set_union_app_id); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (c, "REVOCATION", @@ -562,11 +815,12 @@ run (void *cls, return; } cfg = c; - srv = server; - revocation_map = GNUNET_CONTAINER_multihashmap_create (16, GNUNET_NO); - nc = GNUNET_SERVER_notification_context_create (server, 1); + revocation_map = GNUNET_CONTAINER_multihashmap_create (16, + GNUNET_NO); if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (cfg, "REVOCATION", "WORKBITS", + GNUNET_CONFIGURATION_get_value_number (cfg, + "REVOCATION", + "WORKBITS", &revocation_work_required)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, @@ -588,7 +842,12 @@ run (void *cls, } revocation_set = GNUNET_SET_create (cfg, GNUNET_SET_OPERATION_UNION); - + revocation_union_listen_handle + = GNUNET_SET_listen (cfg, + GNUNET_SET_OPERATION_UNION, + &revocation_set_union_app_id, + &handle_revocation_union_request, + NULL); revocation_db = GNUNET_DISK_file_open (fn, GNUNET_DISK_OPEN_READWRITE | GNUNET_DISK_OPEN_CREATE, @@ -607,10 +866,10 @@ run (void *cls, } if (GNUNET_OK != GNUNET_DISK_file_size (fn, &left, GNUNET_YES, GNUNET_YES)) - left = 0; + left = 0; while (left > sizeof (struct RevokeMessage)) { - rm = GNUNET_new (struct RevokeMessage); + rm = GNUNET_new (struct RevokeMessage); if (sizeof (struct RevokeMessage) != GNUNET_DISK_file_read (revocation_db, rm, @@ -626,72 +885,73 @@ run (void *cls, } GNUNET_break (0 == ntohl (rm->reserved)); GNUNET_CRYPTO_hash (&rm->public_key, - sizeof (struct GNUNET_CRYPTO_EccPublicSignKey), + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), &hc); GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (revocation_map, &hc, rm, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); } GNUNET_free (fn); - - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, - NULL); - peers = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO); - GNUNET_SERVER_add_handlers (srv, handlers); - /* Connect to core service and register core handlers */ - coreAPI = GNUNET_CORE_connect (cfg, /* Main configuration */ - NULL, /* Closure passed to functions */ - &core_init, /* Call core_init once connected */ - &handle_core_connect, /* Handle connects */ - &handle_core_disconnect, /* Handle disconnects */ - NULL, /* Don't want notified about all incoming messages */ - GNUNET_NO, /* For header only inbound notification */ - NULL, /* Don't want notified about all outbound messages */ - GNUNET_NO, /* For header only outbound notification */ - core_handlers); /* Register these handlers */ - if (NULL == coreAPI) + + GNUNET_SCHEDULER_add_shutdown (&shutdown_task, + NULL); + peers = GNUNET_CONTAINER_multipeermap_create (128, + GNUNET_YES); + /* Connect to core service and register core handlers */ + core_api = GNUNET_CORE_connect (cfg, /* Main configuration */ + NULL, /* Closure passed to functions */ + &core_init, /* Call core_init once connected */ + &handle_core_connect, /* Handle connects */ + &handle_core_disconnect, /* Handle disconnects */ + core_handlers); /* Register these handlers */ + if (NULL == core_api) { GNUNET_SCHEDULER_shutdown (); return; } - stats = GNUNET_STATISTICS_create ("revocation", cfg); + stats = GNUNET_STATISTICS_create ("revocation", + cfg); } /** - * The main function for the network size estimation service. - * - * @param argc number of arguments from the command line - * @param argv command line arguments - * @return 0 ok, 1 on error + * Define "main" method using service macro. */ -int -main (int argc, - char *const *argv) -{ - return (GNUNET_OK == - GNUNET_SERVICE_run (argc, argv, "revocation", GNUNET_SERVICE_OPTION_NONE, - &run, NULL)) ? 0 : 1; -} - - -#ifdef LINUX +GNUNET_SERVICE_MAIN +("revocation", + GNUNET_SERVICE_OPTION_NONE, + &run, + &client_connect_cb, + &client_disconnect_cb, + NULL, + GNUNET_MQ_hd_fixed_size (query_message, + GNUNET_MESSAGE_TYPE_REVOCATION_QUERY, + struct QueryMessage, + NULL), + GNUNET_MQ_hd_fixed_size (revoke_message, + GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE, + struct RevokeMessage, + NULL), + GNUNET_MQ_handler_end ()); + + +#if defined(LINUX) && defined(__GLIBC__) #include /** * MINIMIZE heap size (way below 128k) since this process doesn't need much. */ -void __attribute__ ((constructor)) -GNUNET_ARM_memory_init () +void __attribute__ ((constructor)) +GNUNET_REVOCATION_memory_init () { mallopt (M_TRIM_THRESHOLD, 4 * 1024); mallopt (M_TOP_PAD, 1 * 1024); malloc_trim (0); } -#endif +#endif /* end of gnunet-service-revocation.c */