X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fdv%2Fgnunet-service-dv.c;h=84bdc11c23020c69c34710f043ee0140921206ff;hb=37defe2dbd9ea4e5a37710404e8046acbdf4a18e;hp=4479c0b0835808f5dd1af14a873f0dbc1434f1b5;hpb=e649f76bd5eb2d08a976c34f394dd8411130e37c;p=oweals%2Fgnunet.git diff --git a/src/dv/gnunet-service-dv.c b/src/dv/gnunet-service-dv.c index 4479c0b08..84bdc11c2 100644 --- a/src/dv/gnunet-service-dv.c +++ b/src/dv/gnunet-service-dv.c @@ -34,7 +34,7 @@ #include "gnunet_hello_lib.h" #include "gnunet_peerinfo_service.h" #include "gnunet_statistics_service.h" -#include "gnunet_consensus_service.h" +#include "gnunet_set_service.h" #include "gnunet_ats_service.h" #include "dv.h" #include @@ -92,7 +92,7 @@ struct Target /** * Message exchanged between DV services (via core), requesting a - * message to be routed. + * message to be routed. */ struct RouteMessage { @@ -168,7 +168,15 @@ struct DirectNeighbor * Identity of the peer. */ struct GNUNET_PeerIdentity peer; - + + /** + * Session ID we use whenever we create a set union with + * this neighbor; constructed from the XOR of our peer + * IDs and then salted with "DV-SALT" to avoid conflicts + * with other applications. + */ + struct GNUNET_HashCode real_session_id; + /** * Head of linked list of messages to send to this peer. */ @@ -189,8 +197,8 @@ struct DirectNeighbor * Keys are peer identities, values are 'struct Target' entries. * Note that the distances in the targets are from the point-of-view * of the peer, not from us! - */ - struct GNUNET_CONTAINER_MultiHashMap *neighbor_table; + */ + struct GNUNET_CONTAINER_MultiPeerMap *neighbor_table; /** * Updated routing table of the neighbor, under construction, @@ -198,20 +206,31 @@ struct DirectNeighbor * Keys are peer identities, values are 'struct Target' entries. * Note that the distances in the targets are from the point-of-view * of the peer, not from us! - */ - struct GNUNET_CONTAINER_MultiHashMap *neighbor_table_consensus; + */ + struct GNUNET_CONTAINER_MultiPeerMap *neighbor_table_consensus; /** - * Active consensus, if we are currently synchronizing the - * routing tables. + * Our current (exposed) routing table as a set. */ - struct GNUNET_CONSENSUS_Handle *consensus; + struct GNUNET_SET_Handle *my_set; + + /** + * Handle for our current active set union operation. + */ + struct GNUNET_SET_OperationHandle *set_op; + + /** + * Handle used if we are listening for this peer, waiting for the + * other peer to initiate construction of the set union. NULL if + * we ar the initiating peer. + */ + struct GNUNET_SET_ListenHandle *listen_handle; /** * ID of the task we use to (periodically) update our consensus - * with this peer. + * with this peer. Used if we are the initiating peer. */ - GNUNET_SCHEDULER_TaskIdentifier consensus_task; + GNUNET_SCHEDULER_TaskIdentifier initiate_task; /** * At what offset are we, with respect to inserting our own routes @@ -230,6 +249,16 @@ struct DirectNeighbor */ unsigned int pm_queue_size; + /** + * Elements in consensus + */ + unsigned int consensus_elements; + + /** + * Direct one hop route + */ + struct Route *direct_route; + /** * Flag set within 'check_target_removed' to trigger full global route refresh. */ @@ -298,18 +327,18 @@ struct ConsensusSet /** - * Hashmap of all of our neighbors; processing these usually requires - * first checking to see if the peer is core-connected and if the + * Peermap of all of our neighbors; processing these usually requires + * first checking to see if the peer is core-connected and if the * distance is 1, in which case they are direct neighbors. */ -static struct GNUNET_CONTAINER_MultiHashMap *direct_neighbors; +static struct GNUNET_CONTAINER_MultiPeerMap *direct_neighbors; /** - * Hashmap with all routes that we currently support; contains + * Hashmap with all routes that we currently support; contains * routing information for all peers from distance 2 * up to distance DEFAULT_FISHEYE_DEPTH. */ -static struct GNUNET_CONTAINER_MultiHashMap *all_routes; +static struct GNUNET_CONTAINER_MultiPeerMap *all_routes; /** * Array of consensus sets we expose to the outside world. Sets @@ -348,18 +377,41 @@ static struct GNUNET_STATISTICS_Handle *stats; * Handle to ATS service. */ static struct GNUNET_ATS_PerformanceHandle *ats; - + /** - * Start creating a new consensus from scratch. + * Start creating a new DV set union by initiating the connection. * * @param cls the 'struct DirectNeighbor' of the peer we're building * a routing consensus with * @param tc scheduler context - */ + */ static void -start_consensus (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc); +initiate_set_union (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc); + + +/** + * Start creating a new DV set union construction, our neighbour has + * asked for it (callback for listening peer). + * + * @param cls the 'struct DirectNeighbor' of the peer we're building + * a routing consensus with + * @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, use GNUNET_SET_accept + * to accept it, otherwise the request will be refused + * Note that we don't use a return value here, 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. + * Also necessary to specify the timeout. + */ +static void +listen_set_union (void *cls, + const struct GNUNET_PeerIdentity *other_peer, + const struct GNUNET_MessageHeader *context_msg, + struct GNUNET_SET_Request *request); /** @@ -370,7 +422,7 @@ start_consensus (void *cls, * @param distance distance to the original sender of the message */ static void -send_data_to_plugin (const struct GNUNET_MessageHeader *message, +send_data_to_plugin (const struct GNUNET_MessageHeader *message, const struct GNUNET_PeerIdentity *origin, uint32_t distance) { @@ -380,10 +432,10 @@ send_data_to_plugin (const struct GNUNET_MessageHeader *message, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Delivering message from peer `%s'\n", GNUNET_i2s (origin)); - size = sizeof (struct GNUNET_DV_ReceivedMessage) + + size = sizeof (struct GNUNET_DV_ReceivedMessage) + ntohs (message->size); if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE) - { + { GNUNET_break (0); /* too big */ return; } @@ -393,7 +445,7 @@ send_data_to_plugin (const struct GNUNET_MessageHeader *message, received_msg->distance = htonl (distance); received_msg->sender = *origin; memcpy (&received_msg[1], message, ntohs (message->size)); - GNUNET_SERVER_notification_context_broadcast (nc, + GNUNET_SERVER_notification_context_broadcast (nc, &received_msg->header, GNUNET_YES); GNUNET_free (received_msg); @@ -408,7 +460,7 @@ send_data_to_plugin (const struct GNUNET_MessageHeader *message, static void send_control_to_plugin (const struct GNUNET_MessageHeader *message) { - GNUNET_SERVER_notification_context_broadcast (nc, + GNUNET_SERVER_notification_context_broadcast (nc, message, GNUNET_NO); } @@ -422,7 +474,7 @@ send_control_to_plugin (const struct GNUNET_MessageHeader *message) * @param nack GNUNET_NO to send ACK, GNUNET_YES to send NACK */ static void -send_ack_to_plugin (const struct GNUNET_PeerIdentity *target, +send_ack_to_plugin (const struct GNUNET_PeerIdentity *target, uint32_t uid, int nack) { @@ -432,7 +484,7 @@ send_ack_to_plugin (const struct GNUNET_PeerIdentity *target, "Delivering ACK for message to peer `%s'\n", GNUNET_i2s (target)); ack_msg.header.size = htons (sizeof (ack_msg)); - ack_msg.header.type = htons ((GNUNET_YES == nack) + ack_msg.header.type = htons ((GNUNET_YES == nack) ? GNUNET_MESSAGE_TYPE_DV_SEND_NACK : GNUNET_MESSAGE_TYPE_DV_SEND_ACK); ack_msg.uid = htonl (uid); @@ -448,7 +500,7 @@ send_ack_to_plugin (const struct GNUNET_PeerIdentity *target, * @param distance new distance to the peer */ static void -send_distance_change_to_plugin (const struct GNUNET_PeerIdentity *peer, +send_distance_change_to_plugin (const struct GNUNET_PeerIdentity *peer, uint32_t distance) { struct GNUNET_DV_DistanceUpdateMessage du_msg; @@ -471,7 +523,7 @@ send_distance_change_to_plugin (const struct GNUNET_PeerIdentity *peer, * @param distance distance to the target */ static void -send_connect_to_plugin (const struct GNUNET_PeerIdentity *target, +send_connect_to_plugin (const struct GNUNET_PeerIdentity *target, uint32_t distance) { struct GNUNET_DV_ConnectMessage cm; @@ -543,7 +595,7 @@ core_transmit_notify (void *cls, size_t size, void *buf) dn->pm_tail, pending); memcpy (&cbuf[off], pending->msg, msize); - if (0 != pending->uid) + if (0 != pending->uid) send_ack_to_plugin (&pending->ultimate_target, pending->uid, GNUNET_NO); @@ -557,7 +609,7 @@ core_transmit_notify (void *cls, size_t size, void *buf) 0 /* priority */, GNUNET_TIME_UNIT_FOREVER_REL, &dn->peer, - msize, + msize, &core_transmit_notify, dn); return off; } @@ -620,7 +672,7 @@ forward_payload (struct DirectNeighbor *target, 0 /* priority */, GNUNET_TIME_UNIT_FOREVER_REL, &target->peer, - msize, + msize, &core_transmit_notify, target); } @@ -642,9 +694,11 @@ get_consensus_slot (uint32_t distance) while ( (i < cs->array_length) && (NULL != cs->targets[i]) ) i++; if (i == cs->array_length) + { GNUNET_array_grow (cs->targets, cs->array_length, cs->array_length * 2 + 2); + } return i; } @@ -696,11 +750,88 @@ move_route (struct Route *route, release_route (route); i = get_consensus_slot (new_distance); route->set_offset = i; - consensi[new_distance].targets[i] = route; + consensi[new_distance].targets[i] = route; route->target.distance = htonl (new_distance); } +/** + * Initialize this neighbors 'my_set' and when done give + * it to the pending set operation for execution. + * + * Add a single element to the set per call: + * + * If we reached the last element of a consensus element: increase distance + * + * + * @param cls the neighbor for which we are building the set + */ +static void +build_set (void *cls) +{ + struct DirectNeighbor *neighbor = cls; + struct GNUNET_SET_Element element; + struct Target *target; + target = NULL; + while ( (DEFAULT_FISHEYE_DEPTH - 1 > neighbor->consensus_insertion_distance) && + (consensi[neighbor->consensus_insertion_distance].array_length == neighbor->consensus_insertion_offset) ) + { + /* If we reached the last element of a consensus array element: increase distance and start with next array */ + neighbor->consensus_insertion_offset = 0; + neighbor->consensus_insertion_distance++; + /* skip over NULL entries */ + while ( (DEFAULT_FISHEYE_DEPTH - 1 > neighbor->consensus_insertion_distance) && + (consensi[neighbor->consensus_insertion_distance].array_length > neighbor->consensus_insertion_offset) && + (NULL == consensi[neighbor->consensus_insertion_distance].targets[neighbor->consensus_insertion_offset]) ) + neighbor->consensus_insertion_offset++; + } + if (DEFAULT_FISHEYE_DEPTH - 1 == neighbor->consensus_insertion_distance) + { + /* we have added all elements to the set, run the operation */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Finished building my SET for peer `%s' with %u elements, committing\n", + GNUNET_i2s(&neighbor->peer), + neighbor->consensus_elements); + GNUNET_SET_commit (neighbor->set_op, + neighbor->my_set); + GNUNET_SET_destroy (neighbor->my_set); + neighbor->my_set = NULL; + return; + } + + target = &consensi[neighbor->consensus_insertion_distance].targets[neighbor->consensus_insertion_offset]->target; + element.size = sizeof (struct Target); + element.type = htons (0); /* do we need this? */ + element.data = target; + + /* Find next non-NULL entry */ + neighbor->consensus_insertion_offset++; + /* skip over NULL entries */ + while ( (DEFAULT_FISHEYE_DEPTH - 1 > neighbor->consensus_insertion_distance) && + (consensi[neighbor->consensus_insertion_distance].array_length > neighbor->consensus_insertion_offset) && + (NULL == consensi[neighbor->consensus_insertion_distance].targets[neighbor->consensus_insertion_offset]) ) + { + neighbor->consensus_insertion_offset++; + } + + if ( (0 != memcmp(&target->peer, &my_identity, sizeof (my_identity))) && + (0 != memcmp(&target->peer, &neighbor->peer, sizeof (neighbor->peer))) ) + { + /* Add target if it is not the neighbor or this peer */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Adding peer `%s' with distance %u to SET\n", + GNUNET_i2s (&target->peer), + ntohl (target->distance)); + GNUNET_SET_add_element (neighbor->my_set, + &element, + &build_set, neighbor); + neighbor->consensus_elements++; + } + else + build_set(neighbor); +} + + /** * A peer is now connected to us at distance 1. Initiate DV exchange. * @@ -710,20 +841,78 @@ static void handle_direct_connect (struct DirectNeighbor *neighbor) { struct Route *route; + struct GNUNET_HashCode h1; + struct GNUNET_HashCode h2; + struct GNUNET_HashCode session_id; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Direct connection to %s established, routing table exchange begins.\n", + GNUNET_i2s (&neighbor->peer)); GNUNET_STATISTICS_update (stats, "# peers connected (1-hop)", 1, GNUNET_NO); - route = GNUNET_CONTAINER_multihashmap_get (all_routes, - &neighbor->peer.hashPubKey); - if (NULL != route) + route = GNUNET_CONTAINER_multipeermap_get (all_routes, + &neighbor->peer); + if (NULL != route) { send_disconnect_to_plugin (&neighbor->peer); release_route (route); GNUNET_free (route); } - neighbor->consensus_task = GNUNET_SCHEDULER_add_now (&start_consensus, - neighbor); + + neighbor->direct_route = GNUNET_new (struct Route); + neighbor->direct_route->next_hop = neighbor; + neighbor->direct_route->target.peer= neighbor->peer; + neighbor->direct_route->target.distance = DIRECT_NEIGHBOR_COST; + allocate_route (neighbor->direct_route, DIRECT_NEIGHBOR_COST); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Adding direct route to %s\n", + GNUNET_i2s (&neighbor->direct_route->target.peer)); + + + /* construct session ID seed as XOR of both peer's identities */ + GNUNET_CRYPTO_hash (&my_identity, sizeof (my_identity), &h1); + GNUNET_CRYPTO_hash (&neighbor->peer, sizeof (struct GNUNET_PeerIdentity), &h2); + GNUNET_CRYPTO_hash_xor (&h1, + &h2, + &session_id); + /* make sure session ID is unique across applications by salting it with 'DV' */ + GNUNET_CRYPTO_hkdf (&neighbor->real_session_id, sizeof (struct GNUNET_HashCode), + GCRY_MD_SHA512, GCRY_MD_SHA256, + "DV-SALT", 2, + &session_id, sizeof (session_id), + NULL, 0); + if (0 < memcmp (&neighbor->peer, + &my_identity, + sizeof (struct GNUNET_PeerIdentity))) + { + if (NULL != neighbor->listen_handle) + { + GNUNET_break (0); + } + else + neighbor->initiate_task = GNUNET_SCHEDULER_add_now (&initiate_set_union, + neighbor); + } + else + { + if (NULL != neighbor->listen_handle) + { + GNUNET_break (0); + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Starting SET listen operation with peer `%s'\n", + GNUNET_i2s(&neighbor->peer)); + neighbor->listen_handle = GNUNET_SET_listen (cfg, + GNUNET_SET_OPERATION_UNION, + &neighbor->real_session_id, + &listen_set_union, + neighbor); + } + } } @@ -734,30 +923,38 @@ handle_direct_connect (struct DirectNeighbor *neighbor) * @param peer peer identity this notification is about */ static void -handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer) +handle_core_connect (void *cls, + const struct GNUNET_PeerIdentity *peer) { struct DirectNeighbor *neighbor; - + /* Check for connect to self message */ if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity))) return; /* check if entry exists */ - neighbor = GNUNET_CONTAINER_multihashmap_get (direct_neighbors, - &peer->hashPubKey); + neighbor = GNUNET_CONTAINER_multipeermap_get (direct_neighbors, + peer); if (NULL != neighbor) { GNUNET_break (GNUNET_YES != neighbor->connected); neighbor->connected = GNUNET_YES; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Core connected to %s (distance %u)\n", + GNUNET_i2s (peer), + (unsigned int) neighbor->distance); if (DIRECT_NEIGHBOR_COST != neighbor->distance) return; handle_direct_connect (neighbor); return; } - neighbor = GNUNET_malloc (sizeof (struct DirectNeighbor)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Core connected to %s (distance unknown)\n", + GNUNET_i2s (peer)); + neighbor = GNUNET_new (struct DirectNeighbor); neighbor->peer = *peer; GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_put (direct_neighbors, - &peer->hashPubKey, + GNUNET_CONTAINER_multipeermap_put (direct_neighbors, + peer, neighbor, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); neighbor->connected = GNUNET_YES; @@ -775,7 +972,7 @@ handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer) */ static int free_targets (void *cls, - const struct GNUNET_HashCode *key, + const struct GNUNET_PeerIdentity *key, void *value) { GNUNET_free (value); @@ -784,7 +981,7 @@ free_targets (void *cls, /** - * Multihashmap iterator for checking if a given route is + * Multipeerhmap iterator for checking if a given route is * (now) useful to this peer. * * @param cls the direct neighbor for the given route @@ -794,14 +991,16 @@ free_targets (void *cls, * @return GNUNET_YES to continue iteration, GNUNET_NO to stop */ static int -check_possible_route (void *cls, const struct GNUNET_HashCode * key, void *value) +check_possible_route (void *cls, + const struct GNUNET_PeerIdentity *key, + void *value) { struct DirectNeighbor *neighbor = cls; struct Target *target = value; struct Route *route; - - route = GNUNET_CONTAINER_multihashmap_get (all_routes, - key); + + route = GNUNET_CONTAINER_multipeermap_get (all_routes, + key); if (NULL != route) { if (ntohl (route->target.distance) > ntohl (target->distance) + 1) @@ -813,14 +1012,14 @@ check_possible_route (void *cls, const struct GNUNET_HashCode * key, void *value } return GNUNET_YES; /* got a route to this target already */ } - route = GNUNET_malloc (sizeof (struct Route)); + route = GNUNET_new (struct Route); route->next_hop = neighbor; route->target.distance = htonl (ntohl (target->distance) + 1); route->target.peer = target->peer; allocate_route (route, ntohl (route->target.distance)); GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_put (all_routes, - &route->target.peer.hashPubKey, + GNUNET_CONTAINER_multipeermap_put (all_routes, + &route->target.peer, route, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); send_connect_to_plugin (&route->target.peer, ntohl (target->distance)); @@ -829,7 +1028,7 @@ check_possible_route (void *cls, const struct GNUNET_HashCode * key, void *value /** - * Multihashmap iterator for finding routes that were previously + * Multipeermap iterator for finding routes that were previously * "hidden" due to a better route (called after a disconnect event). * * @param cls NULL @@ -838,15 +1037,17 @@ check_possible_route (void *cls, const struct GNUNET_HashCode * key, void *value * @return GNUNET_YES to continue iteration */ static int -refresh_routes (void *cls, const struct GNUNET_HashCode * key, void *value) +refresh_routes (void *cls, + const struct GNUNET_PeerIdentity *key, + void *value) { struct DirectNeighbor *neighbor = value; if ( (GNUNET_YES != neighbor->connected) || (DIRECT_NEIGHBOR_COST != neighbor->distance) ) - return GNUNET_YES; + return GNUNET_YES; if (NULL != neighbor->neighbor_table) - GNUNET_CONTAINER_multihashmap_iterate (neighbor->neighbor_table, + GNUNET_CONTAINER_multipeermap_iterate (neighbor->neighbor_table, &check_possible_route, neighbor); return GNUNET_YES; @@ -868,14 +1069,14 @@ get_atsi_distance (const struct GNUNET_ATS_Information *atsi, for (i = 0; i < atsi_count; i++) if (ntohl (atsi[i].type) == GNUNET_ATS_QUALITY_NET_DISTANCE) - return ntohl (atsi->value); + return (0 == ntohl (atsi->value)) ? DIRECT_NEIGHBOR_COST : ntohl (atsi->value); // FIXME: 0 check should not be required once ATS is fixed! /* If we do not have explicit distance data, assume direct neighbor. */ return DIRECT_NEIGHBOR_COST; } /** - * Multihashmap iterator for freeing routes that go via a particular + * Multipeermap iterator for freeing routes that go via a particular * neighbor that disconnected and is thus no longer available. * * @param cls the direct neighbor that is now unavailable @@ -885,7 +1086,9 @@ get_atsi_distance (const struct GNUNET_ATS_Information *atsi, * @return GNUNET_YES to continue iteration, GNUNET_NO to stop */ static int -cull_routes (void *cls, const struct GNUNET_HashCode * key, void *value) +cull_routes (void *cls, + const struct GNUNET_PeerIdentity *key, + void *value) { struct DirectNeighbor *neighbor = cls; struct Route *route = value; @@ -893,7 +1096,7 @@ cull_routes (void *cls, const struct GNUNET_HashCode * key, void *value) if (route->next_hop != neighbor) return GNUNET_YES; /* not affected */ GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_remove (all_routes, key, value)); + GNUNET_CONTAINER_multipeermap_remove (all_routes, key, value)); release_route (route); send_disconnect_to_plugin (&route->target.peer); GNUNET_free (route); @@ -906,13 +1109,13 @@ cull_routes (void *cls, const struct GNUNET_HashCode * key, void *value) * disrupted. Remove all routes via that peer and * stop the consensus with it. * - * @param neighbor peer that was disconnected (or at least is no + * @param neighbor peer that was disconnected (or at least is no * longer at distance 1) */ static void handle_direct_disconnect (struct DirectNeighbor *neighbor) { - GNUNET_CONTAINER_multihashmap_iterate (all_routes, + GNUNET_CONTAINER_multipeermap_iterate (all_routes, &cull_routes, neighbor); if (NULL != neighbor->cth) @@ -920,31 +1123,49 @@ handle_direct_disconnect (struct DirectNeighbor *neighbor) GNUNET_CORE_notify_transmit_ready_cancel (neighbor->cth); neighbor->cth = NULL; } + + if (NULL != neighbor->direct_route) + { + release_route (neighbor->direct_route); + GNUNET_free (neighbor->direct_route); + neighbor->direct_route = NULL; + } + if (NULL != neighbor->neighbor_table_consensus) { - GNUNET_CONTAINER_multihashmap_iterate (neighbor->neighbor_table_consensus, + GNUNET_CONTAINER_multipeermap_iterate (neighbor->neighbor_table_consensus, &free_targets, NULL); - GNUNET_CONTAINER_multihashmap_destroy (neighbor->neighbor_table_consensus); + GNUNET_CONTAINER_multipeermap_destroy (neighbor->neighbor_table_consensus); neighbor->neighbor_table_consensus = NULL; } if (NULL != neighbor->neighbor_table) { - GNUNET_CONTAINER_multihashmap_iterate (neighbor->neighbor_table, + GNUNET_CONTAINER_multipeermap_iterate (neighbor->neighbor_table, &free_targets, NULL); - GNUNET_CONTAINER_multihashmap_destroy (neighbor->neighbor_table); + GNUNET_CONTAINER_multipeermap_destroy (neighbor->neighbor_table); neighbor->neighbor_table = NULL; } - if (GNUNET_SCHEDULER_NO_TASK != neighbor->consensus_task) + if (NULL != neighbor->set_op) + { + GNUNET_SET_operation_cancel (neighbor->set_op); + neighbor->set_op = NULL; + } + if (NULL != neighbor->my_set) { - GNUNET_SCHEDULER_cancel (neighbor->consensus_task); - neighbor->consensus_task = GNUNET_SCHEDULER_NO_TASK; + GNUNET_SET_destroy (neighbor->my_set); + neighbor->my_set = NULL; } - if (NULL != neighbor->consensus) + if (NULL != neighbor->listen_handle) { - GNUNET_CONSENSUS_destroy (neighbor->consensus); - neighbor->consensus = NULL; + GNUNET_SET_listen_cancel (neighbor->listen_handle); + neighbor->listen_handle = NULL; + } + if (GNUNET_SCHEDULER_NO_TASK != neighbor->initiate_task) + { + GNUNET_SCHEDULER_cancel (neighbor->initiate_task); + neighbor->initiate_task = GNUNET_SCHEDULER_NO_TASK; } } @@ -955,6 +1176,7 @@ handle_direct_disconnect (struct DirectNeighbor *neighbor) * * @param cls closure * @param address the address + * @param active is this address in active use * @param bandwidth_out assigned outbound bandwidth for the connection * @param bandwidth_in assigned inbound bandwidth for the connection * @param ats performance data for the address (as far as known) @@ -962,54 +1184,61 @@ handle_direct_disconnect (struct DirectNeighbor *neighbor) */ static void handle_ats_update (void *cls, - const struct GNUNET_PeerIdentity *peer, + const struct GNUNET_HELLO_Address *address, + int active, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, - const struct GNUNET_ATS_Information *ats, + const struct GNUNET_ATS_Information *ats, uint32_t ats_count) { struct DirectNeighbor *neighbor; uint32_t distance; - /* FIXME: ignore CB if this address is not the one that is in use! */ - distance = get_atsi_distance (ats, ats_count); + if (GNUNET_NO == active) + return; + distance = get_atsi_distance (ats, ats_count); + /* + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "ATS says distance to %s is %u\n", + GNUNET_i2s (&address->peer), + (unsigned int) distance);*/ /* check if entry exists */ - neighbor = GNUNET_CONTAINER_multihashmap_get (direct_neighbors, - &peer->hashPubKey); + neighbor = GNUNET_CONTAINER_multipeermap_get (direct_neighbors, + &address->peer); if (NULL != neighbor) - { + { if ( (DIRECT_NEIGHBOR_COST == neighbor->distance) && (DIRECT_NEIGHBOR_COST == distance) ) return; /* no change */ - if (DIRECT_NEIGHBOR_COST == neighbor->distance) + if (DIRECT_NEIGHBOR_COST == neighbor->distance) { neighbor->distance = distance; GNUNET_STATISTICS_update (stats, "# peers connected (1-hop)", - -1, GNUNET_NO); + -1, GNUNET_NO); handle_direct_disconnect (neighbor); - GNUNET_CONTAINER_multihashmap_iterate (direct_neighbors, + GNUNET_CONTAINER_multipeermap_iterate (direct_neighbors, &refresh_routes, NULL); return; } neighbor->distance = distance; if (DIRECT_NEIGHBOR_COST != neighbor->distance) - return; + return; if (GNUNET_YES != neighbor->connected) return; handle_direct_connect (neighbor); return; } - neighbor = GNUNET_malloc (sizeof (struct DirectNeighbor)); - neighbor->peer = (*peer); + neighbor = GNUNET_new (struct DirectNeighbor); + neighbor->peer = address->peer; GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_put (direct_neighbors, - &peer->hashPubKey, + GNUNET_CONTAINER_multipeermap_put (direct_neighbors, + &address->peer, neighbor, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); neighbor->connected = GNUNET_NO; /* not yet */ - neighbor->distance = distance; + neighbor->distance = distance; } @@ -1024,19 +1253,19 @@ handle_ats_update (void *cls, */ static int check_target_removed (void *cls, - const struct GNUNET_HashCode *key, + const struct GNUNET_PeerIdentity *key, void *value) { struct DirectNeighbor *neighbor = cls; struct Target *new_target; struct Route *current_route; - new_target = GNUNET_CONTAINER_multihashmap_get (neighbor->neighbor_table_consensus, + new_target = GNUNET_CONTAINER_multipeermap_get (neighbor->neighbor_table_consensus, key); if (NULL == new_target) { /* target was revoked, check if it was used */ - current_route = GNUNET_CONTAINER_multihashmap_get (all_routes, + current_route = GNUNET_CONTAINER_multipeermap_get (all_routes, key); if ( (NULL == current_route) || (current_route->next_hop != neighbor) ) @@ -1045,8 +1274,11 @@ check_target_removed (void *cls, return GNUNET_OK; } /* remove existing route */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Lost route to %s\n", + GNUNET_i2s (¤t_route->target.peer)); GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_remove (all_routes, key, current_route)); + GNUNET_CONTAINER_multipeermap_remove (all_routes, key, current_route)); send_disconnect_to_plugin (¤t_route->target.peer); GNUNET_free (current_route); neighbor->target_removed = GNUNET_YES; @@ -1066,15 +1298,15 @@ check_target_removed (void *cls, */ static int check_target_added (void *cls, - const struct GNUNET_HashCode *key, - void *value) + const struct GNUNET_PeerIdentity *key, + void *value) { struct DirectNeighbor *neighbor = cls; struct Target *target = value; struct Route *current_route; /* target was revoked, check if it was used */ - current_route = GNUNET_CONTAINER_multihashmap_get (all_routes, + current_route = GNUNET_CONTAINER_multipeermap_get (all_routes, key); if (NULL != current_route) { @@ -1105,13 +1337,17 @@ check_target_added (void *cls, return GNUNET_OK; } /* new route */ - current_route = GNUNET_malloc (sizeof (struct Route)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Discovered new route to %s using %u hops\n", + GNUNET_i2s (&target->peer), + (unsigned int) (ntohl (target->distance) + 1)); + current_route = GNUNET_new (struct Route); current_route->next_hop = neighbor; current_route->target.peer = target->peer; current_route->target.distance = htonl (ntohl (target->distance) + 1); GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_put (all_routes, - ¤t_route->target.peer.hashPubKey, + GNUNET_CONTAINER_multipeermap_put (all_routes, + ¤t_route->target.peer, current_route, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); send_connect_to_plugin (¤t_route->target.peer, @@ -1120,204 +1356,225 @@ check_target_added (void *cls, } - /** - * The consensus has concluded, clean up and schedule the next one. + * Callback for set operation results. Called for each element + * in the result set. + * We have learned a new route from the other peer. Add it to the + * route set we're building. * - * @param cls the 'struct GNUNET_DirectNeighbor' with which we created the consensus + * @param cls the 'struct DirectNeighbor' we're building the consensus with + * @param element a result element, only valid if status is GNUNET_SET_STATUS_OK + * @param status see enum GNUNET_SET_Status */ static void -consensus_done_cb (void *cls) +handle_set_union_result (void *cls, + const struct GNUNET_SET_Element *element, + enum GNUNET_SET_Status status) { struct DirectNeighbor *neighbor = cls; - - GNUNET_CONSENSUS_destroy (neighbor->consensus); - neighbor->consensus = NULL; - /* remove targets that disappeared */ - neighbor->target_removed = GNUNET_NO; - GNUNET_CONTAINER_multihashmap_iterate (neighbor->neighbor_table, - &check_target_removed, - neighbor); - if (GNUNET_YES == neighbor->target_removed) - { - /* check if we got an alternative for the removed routes */ - GNUNET_CONTAINER_multihashmap_iterate (direct_neighbors, - &refresh_routes, - NULL); + struct Target *target; + char *status_str; + + switch (status) { + case GNUNET_SET_STATUS_OK: + status_str = "GNUNET_SET_STATUS_OK"; + break; + case GNUNET_SET_STATUS_TIMEOUT: + status_str = "GNUNET_SET_STATUS_TIMEOUT"; + break; + case GNUNET_SET_STATUS_FAILURE: + status_str = "GNUNET_SET_STATUS_FAILURE"; + break; + case GNUNET_SET_STATUS_HALF_DONE: + status_str = "GNUNET_SET_STATUS_HALF_DONE"; + break; + case GNUNET_SET_STATUS_DONE: + status_str = "GNUNET_SET_STATUS_DONE"; + break; + default: + status_str = "UNDEFINED"; + break; } - /* add targets that appeared (and check for improved routes) */ - GNUNET_CONTAINER_multihashmap_iterate (neighbor->neighbor_table_consensus, - &check_target_added, - neighbor); - if (NULL != neighbor->neighbor_table) + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Got SET union result: %s\n", + status_str); + switch (status) { - GNUNET_CONTAINER_multihashmap_iterate (neighbor->neighbor_table, - &free_targets, - NULL); - GNUNET_CONTAINER_multihashmap_destroy (neighbor->neighbor_table); - neighbor->neighbor_table = NULL; + case GNUNET_SET_STATUS_OK: + if (sizeof (struct Target) != element->size) + { + GNUNET_break_op (0); + return; + } + target = GNUNET_new (struct Target); + memcpy (target, element->data, sizeof (struct Target)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received information about peer `%s' with distance %u\n", + GNUNET_i2s (&target->peer), ntohl(target->distance)); + if (NULL == neighbor->neighbor_table_consensus) + neighbor->neighbor_table_consensus = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO); + if (GNUNET_YES != + GNUNET_CONTAINER_multipeermap_put (neighbor->neighbor_table_consensus, + &target->peer, + target, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) + { + GNUNET_break_op (0); + GNUNET_free (target); + } + break; + case GNUNET_SET_STATUS_TIMEOUT: + case GNUNET_SET_STATUS_FAILURE: + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Failed to establish DV union, will try again later\n"); + neighbor->set_op = NULL; + if (NULL != neighbor->neighbor_table_consensus) + { + GNUNET_CONTAINER_multipeermap_iterate (neighbor->neighbor_table_consensus, + &free_targets, + NULL); + GNUNET_CONTAINER_multipeermap_destroy (neighbor->neighbor_table_consensus); + neighbor->neighbor_table_consensus = NULL; + } + if (0 < memcmp (&neighbor->peer, + &my_identity, + sizeof (struct GNUNET_PeerIdentity))) + neighbor->initiate_task = GNUNET_SCHEDULER_add_delayed (GNUNET_DV_CONSENSUS_FREQUENCY, + &initiate_set_union, + neighbor); + break; + case GNUNET_SET_STATUS_HALF_DONE: + break; + case GNUNET_SET_STATUS_DONE: + /* we got all of our updates; integrate routing table! */ + neighbor->target_removed = GNUNET_NO; + if (NULL == neighbor->neighbor_table_consensus) + neighbor->neighbor_table_consensus = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO); + if (NULL != neighbor->neighbor_table) + GNUNET_CONTAINER_multipeermap_iterate (neighbor->neighbor_table, + &check_target_removed, + neighbor); + if (GNUNET_YES == neighbor->target_removed) + { + /* check if we got an alternative for the removed routes */ + GNUNET_CONTAINER_multipeermap_iterate (direct_neighbors, + &refresh_routes, + NULL); + } + /* add targets that appeared (and check for improved routes) */ + GNUNET_CONTAINER_multipeermap_iterate (neighbor->neighbor_table_consensus, + &check_target_added, + neighbor); + if (NULL != neighbor->neighbor_table) + { + GNUNET_CONTAINER_multipeermap_iterate (neighbor->neighbor_table, + &free_targets, + NULL); + GNUNET_CONTAINER_multipeermap_destroy (neighbor->neighbor_table); + neighbor->neighbor_table = NULL; + } + neighbor->neighbor_table = neighbor->neighbor_table_consensus; + neighbor->neighbor_table_consensus = NULL; + + /* operation done, schedule next run! */ + neighbor->set_op = NULL; + if (0 < memcmp (&neighbor->peer, + &my_identity, + sizeof (struct GNUNET_PeerIdentity))) + neighbor->initiate_task = GNUNET_SCHEDULER_add_delayed (GNUNET_DV_CONSENSUS_FREQUENCY, + &initiate_set_union, + neighbor); + break; + default: + GNUNET_break (0); + return; } - neighbor->neighbor_table = neighbor->neighbor_table_consensus; - neighbor->neighbor_table_consensus = NULL; - neighbor->consensus_task = GNUNET_SCHEDULER_add_delayed (GNUNET_DV_CONSENSUS_FREQUENCY, - &start_consensus, - neighbor); } /** - * We inserted the last element into the consensus, get ready to - * insert the next element into the consensus or conclude if - * we're done. + * Start creating a new DV set union construction, our neighbour has + * asked for it (callback for listening peer). * * @param cls the 'struct DirectNeighbor' of the peer we're building * a routing consensus with - * @param success GNUNET_OK if the last element was added successfully, - * GNUNET_SYSERR if we failed + * @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, use GNUNET_SET_accept + * to accept it, otherwise the request will be refused + * Note that we don't use a return value here, 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. + * Also necessary to specify the timeout. */ static void -insert_next_element (void *cls, - int success) -{ - struct DirectNeighbor *neighbor = cls; - struct GNUNET_CONSENSUS_Element element; - - while ( (DEFAULT_FISHEYE_DEPTH - 1 > neighbor->consensus_insertion_distance) && - (consensi[neighbor->consensus_insertion_distance].array_length == neighbor->consensus_insertion_offset) ) - { - neighbor->consensus_insertion_offset = 0; - neighbor->consensus_insertion_distance++; - /* skip over NULL entries */ - while ( (DEFAULT_FISHEYE_DEPTH - 1 > neighbor->consensus_insertion_distance) && - (consensi[neighbor->consensus_insertion_distance].array_length < neighbor->consensus_insertion_offset) && - (NULL == consensi[neighbor->consensus_insertion_distance].targets[neighbor->consensus_insertion_offset]) ) - neighbor->consensus_insertion_offset++; - } - if (DEFAULT_FISHEYE_DEPTH - 1 == neighbor->consensus_insertion_distance) - { - /* we're done, conclude! */ - GNUNET_CONSENSUS_conclude (neighbor->consensus, - GNUNET_DV_CONSENSUS_FREQUENCY, - &consensus_done_cb, - neighbor); - return; - } - element.size = sizeof (struct Target); - element.data = &consensi[neighbor->consensus_insertion_distance].targets[neighbor->consensus_insertion_offset++]->target; - - /* skip over NULL entries */ - while ( (DEFAULT_FISHEYE_DEPTH - 1 > neighbor->consensus_insertion_distance) && - (consensi[neighbor->consensus_insertion_distance].array_length < neighbor->consensus_insertion_offset) && - (NULL == consensi[neighbor->consensus_insertion_distance].targets[neighbor->consensus_insertion_offset]) ) - neighbor->consensus_insertion_offset++; - GNUNET_CONSENSUS_insert (neighbor->consensus, - &element, - &insert_next_element, - neighbor); -} - - -/** - * We have learned a new route from the other peer. Add it to the - * route set we're building. - * - * @param cls the 'struct DirectNeighbor' we're building the consensus with - * @param element the new element we have learned - * @return GNUNET_OK if the valid is well-formed and should be added to the consensus, - * GNUNET_SYSERR if the element should be ignored and not be propagated - */ -static int -learn_route_cb (void *cls, - const struct GNUNET_CONSENSUS_Element *element) +listen_set_union (void *cls, + const struct GNUNET_PeerIdentity *other_peer, + const struct GNUNET_MessageHeader *context_msg, + struct GNUNET_SET_Request *request) { struct DirectNeighbor *neighbor = cls; - struct Target *target; - if (NULL == element) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to establish DV consensus, will try again later\n"); - GNUNET_CONSENSUS_destroy (neighbor->consensus); - if (NULL != neighbor->neighbor_table_consensus) - { - GNUNET_CONTAINER_multihashmap_iterate (neighbor->neighbor_table_consensus, - &free_targets, - NULL); - GNUNET_CONTAINER_multihashmap_destroy (neighbor->neighbor_table_consensus); - neighbor->neighbor_table_consensus = NULL; - } - neighbor->consensus = NULL; - neighbor->consensus_task = GNUNET_SCHEDULER_add_delayed (GNUNET_DV_CONSENSUS_FREQUENCY, - &start_consensus, - neighbor); - return GNUNET_SYSERR; - } - if (sizeof (struct Target) != element->size) + if (NULL == request) + return; /* why??? */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Starting to create consensus with %s\n", + GNUNET_i2s (&neighbor->peer)); + if (NULL != neighbor->set_op) { - GNUNET_break_op (0); - return GNUNET_SYSERR; + GNUNET_SET_operation_cancel (neighbor->set_op); + neighbor->set_op = NULL; } - target = GNUNET_malloc (sizeof (struct Target)); - memcpy (target, element->data, sizeof (struct Target)); - if (GNUNET_YES != - GNUNET_CONTAINER_multihashmap_put (neighbor->neighbor_table_consensus, - &target->peer.hashPubKey, - target, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) + if (NULL != neighbor->my_set) { - GNUNET_break_op (0); - GNUNET_free (target); - return GNUNET_SYSERR; + GNUNET_SET_destroy (neighbor->my_set); + neighbor->my_set = NULL; } - return GNUNET_OK; + neighbor->my_set = GNUNET_SET_create (cfg, + GNUNET_SET_OPERATION_UNION); + neighbor->set_op = GNUNET_SET_accept (request, + GNUNET_SET_RESULT_ADDED, + &handle_set_union_result, + neighbor); + neighbor->consensus_insertion_offset = 0; + neighbor->consensus_insertion_distance = 0; + neighbor->consensus_elements = 0; + build_set (neighbor); } /** - * Start creating a new consensus from scratch. + * Start creating a new DV set union by initiating the connection. * * @param cls the 'struct DirectNeighbor' of the peer we're building * a routing consensus with * @param tc scheduler context - */ + */ static void -start_consensus (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) +initiate_set_union (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) { struct DirectNeighbor *neighbor = cls; - struct GNUNET_HashCode session_id; - struct GNUNET_HashCode real_session_id; - neighbor->consensus_task = GNUNET_SCHEDULER_NO_TASK; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Initiating SET union with peer `%s'\n", + GNUNET_i2s (&neighbor->peer)); + neighbor->initiate_task = GNUNET_SCHEDULER_NO_TASK; + neighbor->my_set = GNUNET_SET_create (cfg, + GNUNET_SET_OPERATION_UNION); + neighbor->set_op = GNUNET_SET_prepare (&neighbor->peer, + &neighbor->real_session_id, + NULL, + 0 /* FIXME: salt */, + GNUNET_SET_RESULT_ADDED, + &handle_set_union_result, + neighbor); neighbor->consensus_insertion_offset = 0; neighbor->consensus_insertion_distance = 0; - GNUNET_assert (NULL == neighbor->neighbor_table_consensus); - GNUNET_assert (NULL == neighbor->consensus); - neighbor->neighbor_table_consensus = GNUNET_CONTAINER_multihashmap_create (1024, GNUNET_YES); - /* construct session ID seed as XOR of both peer's identities */ - GNUNET_CRYPTO_hash_xor (&my_identity.hashPubKey, - &neighbor->peer.hashPubKey, - &session_id); - /* make sure session ID is unique across applications by salting it with 'DV' */ - GNUNET_CRYPTO_hkdf (&real_session_id, sizeof (real_session_id), - GCRY_MD_SHA512, GCRY_MD_SHA256, - "DV-SALT", 2, - &session_id, sizeof (session_id), - NULL, 0); - neighbor->consensus = GNUNET_CONSENSUS_create (cfg, - 1, - &neighbor->peer, - &real_session_id, - &learn_route_cb, - neighbor); - if (NULL == neighbor->consensus) - { - neighbor->consensus_task = GNUNET_SCHEDULER_add_delayed (GNUNET_DV_CONSENSUS_FREQUENCY, - &start_consensus, - neighbor); - return; - } - insert_next_element (neighbor, GNUNET_OK); + neighbor->consensus_elements = 0; + build_set (neighbor); } @@ -1340,6 +1597,8 @@ handle_dv_route_message (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *payload; struct Route *route; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Handling DV message\n"); if (ntohs (message->size) < sizeof (struct RouteMessage) + sizeof (struct GNUNET_MessageHeader)) { GNUNET_break_op (0); @@ -1357,8 +1616,8 @@ handle_dv_route_message (void *cls, const struct GNUNET_PeerIdentity *peer, sizeof (struct GNUNET_PeerIdentity))) { /* message is for me, check reverse route! */ - route = GNUNET_CONTAINER_multihashmap_get (all_routes, - &rm->sender.hashPubKey); + route = GNUNET_CONTAINER_multipeermap_get (all_routes, + &rm->sender); if (NULL == route) { /* don't have reverse route, drop */ @@ -1367,13 +1626,16 @@ handle_dv_route_message (void *cls, const struct GNUNET_PeerIdentity *peer, 1, GNUNET_NO); return GNUNET_OK; } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Delivering %u bytes to myself!\n", + ntohs (payload->size)); send_data_to_plugin (payload, &rm->sender, ntohl (route->target.distance)); return GNUNET_OK; } - route = GNUNET_CONTAINER_multihashmap_get (all_routes, - &rm->target.hashPubKey); + route = GNUNET_CONTAINER_multipeermap_get (all_routes, + &rm->target); if (NULL == route) { GNUNET_STATISTICS_update (stats, @@ -1388,13 +1650,16 @@ handle_dv_route_message (void *cls, const struct GNUNET_PeerIdentity *peer, 1, GNUNET_NO); return GNUNET_OK; } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Forwarding message to %s\n", + GNUNET_i2s (&rm->target)); forward_payload (route->next_hop, ntohl (route->target.distance), 0, &rm->target, &rm->sender, payload); - return GNUNET_OK; + return GNUNET_OK; } @@ -1429,8 +1694,8 @@ handle_dv_send_message (void *cls, struct GNUNET_SERVER_Client *client, GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } - route = GNUNET_CONTAINER_multihashmap_get (all_routes, - &msg->target.hashPubKey); + route = GNUNET_CONTAINER_multipeermap_get (all_routes, + &msg->target); if (NULL == route) { /* got disconnected */ @@ -1441,6 +1706,11 @@ handle_dv_send_message (void *cls, struct GNUNET_SERVER_Client *client, GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Forwarding %u bytes to %s\n", + ntohs (payload->size), + GNUNET_i2s (&msg->target)); + forward_payload (route->next_hop, ntohl (route->target.distance), htonl (msg->uid), @@ -1466,13 +1736,13 @@ cleanup_neighbor (struct DirectNeighbor *neighbor) neighbor->pm_queue_size--; GNUNET_CONTAINER_DLL_remove (neighbor->pm_head, neighbor->pm_tail, - pending); + pending); GNUNET_free (pending); } handle_direct_disconnect (neighbor); GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_remove (direct_neighbors, - &neighbor->peer.hashPubKey, + GNUNET_CONTAINER_multipeermap_remove (direct_neighbors, + &neighbor->peer, neighbor)); GNUNET_free (neighbor); } @@ -1496,7 +1766,7 @@ handle_core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity))) return; neighbor = - GNUNET_CONTAINER_multihashmap_get (direct_neighbors, &peer->hashPubKey); + GNUNET_CONTAINER_multipeermap_get (direct_neighbors, peer); if (NULL == neighbor) { GNUNET_break (0); @@ -1506,19 +1776,20 @@ handle_core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) neighbor->connected = GNUNET_NO; if (DIRECT_NEIGHBOR_COST == neighbor->distance) { + GNUNET_STATISTICS_update (stats, "# peers connected (1-hop)", - -1, GNUNET_NO); + -1, GNUNET_NO); } cleanup_neighbor (neighbor); - GNUNET_CONTAINER_multihashmap_iterate (direct_neighbors, + GNUNET_CONTAINER_multipeermap_iterate (direct_neighbors, &refresh_routes, NULL); } /** - * Multihashmap iterator for freeing routes. Should never be called. + * Multipeermap iterator for freeing routes. Should never be called. * * @param cls NULL * @param key key value stored under @@ -1527,13 +1798,13 @@ handle_core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) * @return GNUNET_YES to continue iteration, GNUNET_NO to stop */ static int -free_route (void *cls, const struct GNUNET_HashCode * key, void *value) +free_route (void *cls, const struct GNUNET_PeerIdentity * key, void *value) { struct Route *route = value; GNUNET_break (0); GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_remove (all_routes, key, value)); + GNUNET_CONTAINER_multipeermap_remove (all_routes, key, value)); release_route (route); send_disconnect_to_plugin (&route->target.peer); GNUNET_free (route); @@ -1542,7 +1813,7 @@ free_route (void *cls, const struct GNUNET_HashCode * key, void *value) /** - * Multihashmap iterator for freeing direct neighbors. Should never be called. + * Multipeermap iterator for freeing direct neighbors. Should never be called. * * @param cls NULL * @param key key value stored under @@ -1551,7 +1822,7 @@ free_route (void *cls, const struct GNUNET_HashCode * key, void *value) * @return GNUNET_YES to continue iteration, GNUNET_NO to stop */ static int -free_direct_neighbors (void *cls, const struct GNUNET_HashCode * key, void *value) +free_direct_neighbors (void *cls, const struct GNUNET_PeerIdentity * key, void *value) { struct DirectNeighbor *neighbor = value; @@ -1576,12 +1847,12 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) core_api = NULL; GNUNET_ATS_performance_done (ats); ats = NULL; - GNUNET_CONTAINER_multihashmap_iterate (direct_neighbors, + GNUNET_CONTAINER_multipeermap_iterate (direct_neighbors, &free_direct_neighbors, NULL); - GNUNET_CONTAINER_multihashmap_iterate (all_routes, + GNUNET_CONTAINER_multipeermap_iterate (all_routes, &free_route, NULL); - GNUNET_CONTAINER_multihashmap_destroy (direct_neighbors); - GNUNET_CONTAINER_multihashmap_destroy (all_routes); + GNUNET_CONTAINER_multipeermap_destroy (direct_neighbors); + GNUNET_CONTAINER_multipeermap_destroy (all_routes); GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; GNUNET_SERVER_notification_context_destroy (nc); @@ -1603,19 +1874,19 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) */ static int add_route (void *cls, - const struct GNUNET_HashCode *key, + const struct GNUNET_PeerIdentity *key, void *value) { struct GNUNET_SERVER_Client *client = cls; struct Route *route = value; struct GNUNET_DV_ConnectMessage cm; - + cm.header.size = htons (sizeof (cm)); cm.header.type = htons (GNUNET_MESSAGE_TYPE_DV_CONNECT); cm.distance = htonl (route->target.distance); cm.peer = route->target.peer; - GNUNET_SERVER_notification_context_unicast (nc, + GNUNET_SERVER_notification_context_unicast (nc, client, &cm.header, GNUNET_NO); @@ -1635,9 +1906,9 @@ static void handle_start (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { - GNUNET_SERVER_notification_context_add (nc, client); + GNUNET_SERVER_notification_context_add (nc, client); GNUNET_SERVER_receive_done (client, GNUNET_OK); - GNUNET_CONTAINER_multihashmap_iterate (all_routes, + GNUNET_CONTAINER_multipeermap_iterate (all_routes, &add_route, client); } @@ -1647,11 +1918,10 @@ handle_start (void *cls, struct GNUNET_SERVER_Client *client, * Called on core init. * * @param cls unused - * @param server legacy * @param identity this peer's identity */ static void -core_init (void *cls, struct GNUNET_CORE_Handle *server, +core_init (void *cls, const struct GNUNET_PeerIdentity *identity) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, @@ -1677,29 +1947,29 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, {NULL, 0, 0} }; static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = { - {&handle_start, NULL, - GNUNET_MESSAGE_TYPE_DV_START, + {&handle_start, NULL, + GNUNET_MESSAGE_TYPE_DV_START, sizeof (struct GNUNET_MessageHeader) }, - { &handle_dv_send_message, NULL, - GNUNET_MESSAGE_TYPE_DV_SEND, + { &handle_dv_send_message, NULL, + GNUNET_MESSAGE_TYPE_DV_SEND, 0}, {NULL, NULL, 0, 0} }; cfg = c; - direct_neighbors = GNUNET_CONTAINER_multihashmap_create (128, GNUNET_NO); - all_routes = GNUNET_CONTAINER_multihashmap_create (65536, GNUNET_NO); + direct_neighbors = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO); + all_routes = GNUNET_CONTAINER_multipeermap_create (65536, GNUNET_NO); core_api = GNUNET_CORE_connect (cfg, NULL, - &core_init, + &core_init, &handle_core_connect, &handle_core_disconnect, - NULL, GNUNET_NO, - NULL, GNUNET_NO, + NULL, GNUNET_NO, + NULL, GNUNET_NO, core_handlers); if (NULL == core_api) return; - ats = GNUNET_ATS_performance_init (cfg, &handle_ats_update, NULL, NULL, NULL); + ats = GNUNET_ATS_performance_init (cfg, &handle_ats_update, NULL); if (NULL == ats) { GNUNET_CORE_disconnect (core_api);