X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fdht%2Fgnunet-service-dht_neighbours.c;h=8ab39c9aaf71d132c8ec3c459197e416b82004e0;hb=3b680a20ab2cbb98cfa658d85be7a44baaf95d2c;hp=9608405efb501370518fb5d64ccdc325222c58ac;hpb=f1f603c7d0b3f03dca46a4f313472288eb080eb1;p=oweals%2Fgnunet.git diff --git a/src/dht/gnunet-service-dht_neighbours.c b/src/dht/gnunet-service-dht_neighbours.c index 9608405ef..8ab39c9aa 100644 --- a/src/dht/gnunet-service-dht_neighbours.c +++ b/src/dht/gnunet-service-dht_neighbours.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2009-2013 Christian Grothoff (and other contributing authors) + Copyright (C) 2009-2015 GNUnet e.V. GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -14,8 +14,8 @@ You should have received a copy of the GNU General Public License 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. */ /** @@ -45,7 +45,6 @@ #include "gnunet-service-dht_neighbours.h" #include "gnunet-service-dht_nse.h" #include "gnunet-service-dht_routing.h" -#include #include "dht.h" #define LOG_TRAFFIC(kind,...) GNUNET_log_from (kind, "dht-traffic",__VA_ARGS__) @@ -75,11 +74,6 @@ */ #define MAXIMUM_PENDING_PER_PEER 64 -/** - * How often to update our preference levels for peers in our routing tables. - */ -#define DHT_DEFAULT_PREFERENCE_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2) - /** * How long at least to wait before sending another find peer request. */ @@ -331,11 +325,6 @@ struct PeerInfo */ struct GNUNET_CORE_TransmitHandle *th; - /** - * Task for scheduling preference updates - */ - struct GNUNET_SCHEDULER_Task * preference_task; - /** * What is the identity of the peer? */ @@ -378,6 +367,29 @@ struct PeerBucket }; +/** + * Information about a peer that we would like to connect to. + */ +struct ConnectInfo +{ + + /** + * Handle to active HELLO offer operation, or NULL. + */ + struct GNUNET_TRANSPORT_OfferHelloHandle *oh; + + /** + * Handle to active connectivity suggestion operation, or NULL. + */ + struct GNUNET_ATS_ConnectivitySuggestHandle *sh; + + /** + * How much would we like to connect to this peer? + */ + uint32_t strength; +}; + + /** * Do we cache all results that we are routing in the local datacache? */ @@ -405,14 +417,21 @@ static unsigned int newly_found_peers; static int disable_try_connect; /** - * The buckets. Array of size MAX_BUCKET_SIZE. Offset 0 means 0 bits matching. + * The buckets. Array of size #MAX_BUCKETS. Offset 0 means 0 bits matching. */ static struct PeerBucket k_buckets[MAX_BUCKETS]; /** - * Hash map of all known peers, for easy removal from k_buckets on disconnect. + * Hash map of all CORE-connected peers, for easy removal from + * #k_buckets on disconnect. Values are of type `struct PeerInfo`. */ -static struct GNUNET_CONTAINER_MultiPeerMap *all_known_peers; +static struct GNUNET_CONTAINER_MultiPeerMap *all_connected_peers; + +/** + * Hash map of all peers we would like to be connected to. + * Values are of type `struct ConnectInfo`. + */ +static struct GNUNET_CONTAINER_MultiPeerMap *all_desired_peers; /** * Maximum size for each bucket. @@ -422,7 +441,7 @@ static unsigned int bucket_size = DEFAULT_BUCKET_SIZE; /** * Task that sends FIND PEER requests. */ -static struct GNUNET_SCHEDULER_Task * find_peer_task; +static struct GNUNET_SCHEDULER_Task *find_peer_task; /** * Identity of this peer. @@ -440,10 +459,9 @@ static struct GNUNET_HashCode my_identity_hash; static struct GNUNET_CORE_Handle *core_api; /** - * Handle to ATS. + * Handle to ATS connectivity. */ -static struct GNUNET_ATS_PerformanceHandle *atsAPI; - +static struct GNUNET_ATS_ConnectivityHandle *ats_ch; /** @@ -470,63 +488,170 @@ find_bucket (const struct GNUNET_HashCode *hc) /** - * Let GNUnet core know that we like the given peer. + * Function called when #GNUNET_TRANSPORT_offer_hello() is done. + * Clean up the "oh" field in the @a cls * - * @param cls the `struct PeerInfo` of the peer - * @param tc scheduler context. + * @param cls a `struct ConnectInfo` */ static void -update_core_preference (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) +offer_hello_done (void *cls) +{ + struct ConnectInfo *ci = cls; + + ci->oh = NULL; +} + + +/** + * Function called for all entries in #all_desired_peers to clean up. + * + * @param cls NULL + * @param peer peer the entry is for + * @param value the value to remove + * @return #GNUNET_YES + */ +static int +free_connect_info (void *cls, + const struct GNUNET_PeerIdentity *peer, + void *value) +{ + struct ConnectInfo *ci = value; + + GNUNET_assert (GNUNET_YES == + GNUNET_CONTAINER_multipeermap_remove (all_desired_peers, + peer, + ci)); + if (NULL != ci->sh) + { + GNUNET_ATS_connectivity_suggest_cancel (ci->sh); + ci->sh = NULL; + } + if (NULL != ci->oh) + { + GNUNET_TRANSPORT_offer_hello_cancel (ci->oh); + ci->oh = NULL; + } + GNUNET_free (ci); + return GNUNET_YES; +} + + +/** + * Consider if we want to connect to a given peer, and if so + * let ATS know. If applicable, the HELLO is offered to the + * TRANSPORT service. + * + * @param pid peer to consider connectivity requirements for + * @param h a HELLO message, or NULL + */ +static void +try_connect (const struct GNUNET_PeerIdentity *pid, + const struct GNUNET_MessageHeader *h) { - struct PeerInfo *peer = cls; - uint64_t preference; - unsigned int matching; int bucket; - struct GNUNET_HashCode phash; + struct GNUNET_HashCode pid_hash; + struct ConnectInfo *ci; + uint32_t strength; - peer->preference_task = NULL; - if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) - return; - GNUNET_CRYPTO_hash (&peer->id, - sizeof (struct GNUNET_PeerIdentity), - &phash); - matching = - GNUNET_CRYPTO_hash_matching_bits (&my_identity_hash, - &phash); - if (matching >= 64) - matching = 63; - bucket = find_bucket (&phash); - if (bucket == GNUNET_SYSERR) - preference = 0; + GNUNET_CRYPTO_hash (pid, + sizeof (struct GNUNET_PeerIdentity), + &pid_hash); + bucket = find_bucket (&pid_hash); + if (bucket < 0) + return; /* self? */ + ci = GNUNET_CONTAINER_multipeermap_get (all_desired_peers, + pid); + + if (k_buckets[bucket].peers_size < bucket_size) + strength = (bucket_size - k_buckets[bucket].peers_size) * bucket; else + strength = bucket; /* minimum value of connectivity */ + if (GNUNET_YES == + GNUNET_CONTAINER_multipeermap_contains (all_connected_peers, + pid)) + strength *= 2; /* double for connected peers */ + else if (k_buckets[bucket].peers_size > bucket_size) + strength = 0; /* bucket full, we really do not care about more */ + + if ( (0 == strength) && + (NULL != ci) ) { - GNUNET_assert (k_buckets[bucket].peers_size != 0); - preference = (1LL << matching) / k_buckets[bucket].peers_size; + /* release request */ + GNUNET_assert (GNUNET_YES == + free_connect_info (NULL, + pid, + ci)); + return; } - if (preference == 0) + if (NULL == ci) { - peer->preference_task = - GNUNET_SCHEDULER_add_delayed (DHT_DEFAULT_PREFERENCE_INTERVAL, - &update_core_preference, peer); - return; + ci = GNUNET_new (struct ConnectInfo); + GNUNET_assert (GNUNET_OK == + GNUNET_CONTAINER_multipeermap_put (all_desired_peers, + pid, + ci, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); } - GNUNET_STATISTICS_update (GDS_stats, - gettext_noop ("# Preference updates given to core"), - 1, GNUNET_NO); - GNUNET_ATS_performance_change_preference (atsAPI, &peer->id, - GNUNET_ATS_PREFERENCE_BANDWIDTH, - (double) preference, GNUNET_ATS_PREFERENCE_END); - peer->preference_task = - GNUNET_SCHEDULER_add_delayed (DHT_DEFAULT_PREFERENCE_INTERVAL, - &update_core_preference, peer); + if ( (NULL != GDS_transport_handle) && + (NULL != ci->oh) && + (NULL != h) ) + GNUNET_TRANSPORT_offer_hello_cancel (ci->oh); + if ( (NULL != GDS_transport_handle) && + (NULL != h) ) + ci->oh = GNUNET_TRANSPORT_offer_hello (GDS_transport_handle, + h, + &offer_hello_done, + ci); + if ( (NULL != ci->sh) && + (ci->strength != strength) ) + GNUNET_ATS_connectivity_suggest_cancel (ci->sh); + if (ci->strength != strength) + ci->sh = GNUNET_ATS_connectivity_suggest (ats_ch, + pid, + strength); + ci->strength = strength; +} +/** + * Function called for each peer in #all_desired_peers during + * #update_connect_preferences() if we have reason to adjust + * the strength of our desire to keep connections to certain + * peers. Calls #try_connect() to update the calculations for + * the given @a pid. + * + * @param cls NULL + * @param pid peer to update + * @param value unused + * @return #GNUNET_YES (continue to iterate) + */ +static int +update_desire_strength (void *cls, + const struct GNUNET_PeerIdentity *pid, + void *value) +{ + try_connect (pid, NULL); + return GNUNET_YES; +} + + +/** + * Update our preferences for connectivity as given to ATS. + * + * @param cls the `struct PeerInfo` of the peer + * @param tc scheduler context. + */ +static void +update_connect_preferences () +{ + GNUNET_CONTAINER_multipeermap_iterate (all_desired_peers, + &update_desire_strength, + NULL); } /** - * Closure for 'add_known_to_bloom'. + * Closure for #add_known_to_bloom(). */ struct BloomConstructorContext { @@ -560,8 +685,12 @@ add_known_to_bloom (void *cls, struct GNUNET_HashCode key_hash; struct GNUNET_HashCode mh; - GNUNET_CRYPTO_hash (key, sizeof (struct GNUNET_PeerIdentity), &key_hash); - GNUNET_BLOCK_mingle_hash (&key_hash, ctx->bf_mutator, &mh); + GNUNET_CRYPTO_hash (key, + sizeof (struct GNUNET_PeerIdentity), + &key_hash); + GNUNET_BLOCK_mingle_hash (&key_hash, + ctx->bf_mutator, + &mh); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding known peer (%s) to bloomfilter for FIND PEER with mutation %u\n", GNUNET_i2s (key), ctx->bf_mutator); @@ -576,19 +705,15 @@ add_known_to_bloom (void *cls, * and attempt to connect to them. * * @param cls closure for this task - * @param tc the context under which the task is running */ static void -send_find_peer_message (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) +send_find_peer_message (void *cls) { struct GNUNET_TIME_Relative next_send_time; struct BloomConstructorContext bcc; struct GNUNET_CONTAINER_BloomFilter *peer_bf; find_peer_task = NULL; - if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) - return; if (newly_found_peers > bucket_size) { /* If we are finding many peers already, no need to send out our request right now! */ @@ -603,7 +728,8 @@ send_find_peer_message (void *cls, bcc.bloom = GNUNET_CONTAINER_bloomfilter_init (NULL, DHT_BLOOM_SIZE, GNUNET_CONSTANTS_BLOOMFILTER_K); - GNUNET_CONTAINER_multipeermap_iterate (all_known_peers, &add_known_to_bloom, + GNUNET_CONTAINER_multipeermap_iterate (all_connected_peers, + &add_known_to_bloom, &bcc); GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# FIND PEER messages initiated"), 1, @@ -639,7 +765,8 @@ send_find_peer_message (void *cls, * @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 PeerInfo *ret; struct GNUNET_HashCode phash; @@ -652,13 +779,15 @@ handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer) "Connected to %s\n", GNUNET_i2s (peer)); if (GNUNET_YES == - GNUNET_CONTAINER_multipeermap_contains (all_known_peers, + GNUNET_CONTAINER_multipeermap_contains (all_connected_peers, peer)) { GNUNET_break (0); return; } - GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# peers connected"), 1, + GNUNET_STATISTICS_update (GDS_stats, + gettext_noop ("# peers connected"), + 1, GNUNET_NO); GNUNET_CRYPTO_hash (peer, sizeof (struct GNUNET_PeerIdentity), @@ -672,24 +801,28 @@ handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer) #endif ret->id = *peer; GNUNET_CONTAINER_DLL_insert_tail (k_buckets[peer_bucket].head, - k_buckets[peer_bucket].tail, ret); + k_buckets[peer_bucket].tail, + ret); k_buckets[peer_bucket].peers_size++; - closest_bucket = GNUNET_MAX (closest_bucket, peer_bucket); - if ((peer_bucket > 0) && (k_buckets[peer_bucket].peers_size <= bucket_size)) + closest_bucket = GNUNET_MAX (closest_bucket, + peer_bucket); + GNUNET_assert (GNUNET_OK == + GNUNET_CONTAINER_multipeermap_put (all_connected_peers, + peer, + ret, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); + if ( (peer_bucket > 0) && + (k_buckets[peer_bucket].peers_size <= bucket_size)) { - ret->preference_task = - GNUNET_SCHEDULER_add_now (&update_core_preference, ret); + update_connect_preferences (); newly_found_peers++; } - GNUNET_assert (GNUNET_OK == - GNUNET_CONTAINER_multipeermap_put (all_known_peers, - peer, ret, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); - if (1 == GNUNET_CONTAINER_multipeermap_size (all_known_peers) && + if (1 == GNUNET_CONTAINER_multipeermap_size (all_connected_peers) && (GNUNET_YES != disable_try_connect)) { /* got a first connection, good time to start with FIND PEER requests... */ - find_peer_task = GNUNET_SCHEDULER_add_now (&send_find_peer_message, NULL); + find_peer_task = GNUNET_SCHEDULER_add_now (&send_find_peer_message, + NULL); } } @@ -711,42 +844,43 @@ handle_core_disconnect (void *cls, struct GNUNET_HashCode phash; /* Check for disconnect from self message */ - if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity))) + if (0 == memcmp (&my_identity, + peer, + sizeof (struct GNUNET_PeerIdentity))) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnected %s\n", GNUNET_i2s (peer)); to_remove = - GNUNET_CONTAINER_multipeermap_get (all_known_peers, peer); + GNUNET_CONTAINER_multipeermap_get (all_connected_peers, + peer); if (NULL == to_remove) { GNUNET_break (0); return; } - GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# peers connected"), -1, + GNUNET_STATISTICS_update (GDS_stats, + gettext_noop ("# peers connected"), + -1, GNUNET_NO); GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multipeermap_remove (all_known_peers, + GNUNET_CONTAINER_multipeermap_remove (all_connected_peers, peer, to_remove)); - if (NULL != to_remove->preference_task) - { - GNUNET_SCHEDULER_cancel (to_remove->preference_task); - to_remove->preference_task = NULL; - } GNUNET_CRYPTO_hash (peer, sizeof (struct GNUNET_PeerIdentity), &phash); current_bucket = find_bucket (&phash); GNUNET_assert (current_bucket >= 0); GNUNET_CONTAINER_DLL_remove (k_buckets[current_bucket].head, - k_buckets[current_bucket].tail, to_remove); + k_buckets[current_bucket].tail, + to_remove); GNUNET_assert (k_buckets[current_bucket].peers_size > 0); k_buckets[current_bucket].peers_size--; - while ((closest_bucket > 0) && (k_buckets[closest_bucket].peers_size == 0)) + while ( (closest_bucket > 0) && + (0 == k_buckets[closest_bucket].peers_size) ) closest_bucket--; - - if (to_remove->th != NULL) + if (NULL != to_remove->th) { GNUNET_CORE_notify_transmit_ready_cancel (to_remove->th); to_remove->th = NULL; @@ -754,14 +888,18 @@ handle_core_disconnect (void *cls, discarded = 0; while (NULL != (pos = to_remove->head)) { - GNUNET_CONTAINER_DLL_remove (to_remove->head, to_remove->tail, pos); + GNUNET_CONTAINER_DLL_remove (to_remove->head, + to_remove->tail, + pos); discarded++; GNUNET_free (pos); } + if (k_buckets[current_bucket].peers_size < bucket_size) + update_connect_preferences (); GNUNET_STATISTICS_update (GDS_stats, - gettext_noop - ("# Queued messages discarded (peer disconnected)"), - discarded, GNUNET_NO); + gettext_noop ("# Queued messages discarded (peer disconnected)"), + discarded, + GNUNET_NO); GNUNET_free (to_remove); } @@ -771,12 +909,14 @@ handle_core_disconnect (void *cls, * out to the destination. * * @param cls the 'struct PeerInfo' of the target peer - * @param size number of bytes available in buf + * @param size number of bytes available in @a buf * @param buf where the callee should write the message - * @return number of bytes written to buf + * @return number of bytes written to @a buf */ static size_t -core_transmit_notify (void *cls, size_t size, void *buf) +core_transmit_notify (void *cls, + size_t size, + void *buf) { struct PeerInfo *peer = cls; char *cbuf = buf; @@ -825,17 +965,25 @@ core_transmit_notify (void *cls, size_t size, void *buf) memcpy (&cbuf[off], pending->msg, msize); off += msize; peer->pending_count--; - GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending); + GNUNET_CONTAINER_DLL_remove (peer->head, + peer->tail, + pending); GNUNET_free (pending); } - if (peer->head != NULL) + if (NULL != (pending = peer->head)) { + /* technically redundant, but easier to read and + avoids bogus gcc warning... */ + msize = ntohs (pending->msg->size); peer->th = - GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO, - GNUNET_CORE_PRIO_BEST_EFFORT, - GNUNET_TIME_absolute_get_remaining - (pending->timeout), &peer->id, msize, - &core_transmit_notify, peer); + GNUNET_CORE_notify_transmit_ready (core_api, + GNUNET_NO, + GNUNET_CORE_PRIO_BEST_EFFORT, + GNUNET_TIME_absolute_get_remaining (pending->timeout), + &peer->id, + msize, + &core_transmit_notify, + peer); GNUNET_break (NULL != peer->th); } return off; @@ -864,9 +1012,11 @@ process_peer_queue (struct PeerInfo *peer) GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO, GNUNET_CORE_PRIO_BEST_EFFORT, GNUNET_TIME_absolute_get_remaining - (pending->timeout), &peer->id, + (pending->timeout), + &peer->id, ntohs (pending->msg->size), - &core_transmit_notify, peer); + &core_transmit_notify, + peer); GNUNET_break (NULL != peer->th); } @@ -1008,12 +1158,12 @@ am_closest_peer (const struct GNUNET_HashCode *key, bits = GNUNET_CRYPTO_hash_matching_bits (&my_identity_hash, key); pos = k_buckets[bucket_num].head; count = 0; - while ((pos != NULL) && (count < bucket_size)) + while ((NULL != pos) && (count < bucket_size)) { GNUNET_CRYPTO_hash (&pos->id, sizeof (struct GNUNET_PeerIdentity), &phash); - if ((bloom != NULL) && + if ((NULL != bloom) && (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (bloom, &phash))) { @@ -1050,8 +1200,9 @@ am_closest_peer (const struct GNUNET_HashCode *key, * @return Peer to route to, or NULL on error */ static struct PeerInfo * -select_peer (const struct GNUNET_HashCode * key, - const struct GNUNET_CONTAINER_BloomFilter *bloom, uint32_t hops) +select_peer (const struct GNUNET_HashCode *key, + const struct GNUNET_CONTAINER_BloomFilter *bloom, + uint32_t hops) { unsigned int bc; unsigned int count; @@ -1223,9 +1374,12 @@ get_target_peers (const struct GNUNET_HashCode *key, GNUNET_CONTAINER_bloomfilter_add (bloom, &nhash); } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Selected %u/%u peers at hop %u for %s (target was %u)\n", off, - GNUNET_CONTAINER_multipeermap_size (all_known_peers), - (unsigned int) hop_count, GNUNET_h2s (key), ret); + "Selected %u/%u peers at hop %u for %s (target was %u)\n", + off, + GNUNET_CONTAINER_multipeermap_size (all_connected_peers), + (unsigned int) hop_count, + GNUNET_h2s (key), + ret); if (0 == off) { GNUNET_free (rtargets); @@ -1522,12 +1676,13 @@ void GDS_NEIGHBOURS_handle_reply (const struct GNUNET_PeerIdentity *target, enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute expiration_time, - const struct GNUNET_HashCode * key, + const struct GNUNET_HashCode *key, unsigned int put_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *get_path, - const void *data, size_t data_size) + const void *data, + size_t data_size) { struct PeerInfo *pi; struct P2PPendingMessage *pending; @@ -1549,7 +1704,8 @@ GDS_NEIGHBOURS_handle_reply (const struct GNUNET_PeerIdentity *target, GNUNET_break (0); return; } - pi = GNUNET_CONTAINER_multipeermap_get (all_known_peers, target); + pi = GNUNET_CONTAINER_multipeermap_get (all_connected_peers, + target); if (NULL == pi) { /* peer disconnected in the meantime, drop reply */ @@ -1708,6 +1864,7 @@ handle_dht_p2p_put (void *cls, const struct GNUNET_PeerIdentity *peer, { switch (GNUNET_BLOCK_evaluate (GDS_block_context, ntohl (put->type), + GNUNET_BLOCK_EO_NONE, NULL, /* query */ NULL, 0, /* bloom filer */ NULL, 0, /* xquery */ @@ -1761,12 +1918,16 @@ handle_dht_p2p_put (void *cls, const struct GNUNET_PeerIdentity *peer, ntohl (put->desired_replication_level), GNUNET_TIME_absolute_ntoh (put->expiration_time), ntohl (put->hop_count), bf, - &put->key, putlen, - pp, payload, payload_size); + &put->key, + putlen, + pp, + payload, + payload_size); /* notify monitoring clients */ GDS_CLIENTS_process_put (options - | (GNUNET_OK == forwarded) - ? GNUNET_DHT_RO_LAST_HOP : 0, + | ( (GNUNET_OK == forwarded) + ? GNUNET_DHT_RO_LAST_HOP + : 0 ), ntohl (put->type), ntohl (put->hop_count), ntohl (put->desired_replication_level), @@ -1953,8 +2114,16 @@ handle_dht_p2p_get (void *cls, GNUNET_CONTAINER_bloomfilter_init (&xquery[xquery_size], reply_bf_size, GNUNET_CONSTANTS_BLOOMFILTER_K); eval = - GNUNET_BLOCK_evaluate (GDS_block_context, type, &get->key, &reply_bf, - get->bf_mutator, xquery, xquery_size, NULL, 0); + GNUNET_BLOCK_evaluate (GDS_block_context, + type, + GNUNET_BLOCK_EO_NONE, + &get->key, + &reply_bf, + get->bf_mutator, + xquery, + xquery_size, + NULL, + 0); if (eval != GNUNET_BLOCK_EVALUATION_REQUEST_VALID) { /* request invalid or block type not supported */ @@ -2041,7 +2210,8 @@ handle_dht_p2p_get (void *cls, * @return #GNUNET_YES (do not cut p2p connection) */ static int -handle_dht_p2p_result (void *cls, const struct GNUNET_PeerIdentity *peer, +handle_dht_p2p_result (void *cls, + const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { const struct PeerResultMessage *prm; @@ -2094,17 +2264,19 @@ handle_dht_p2p_result (void *cls, const struct GNUNET_PeerIdentity *peer, char *tmp; tmp = GNUNET_strdup (GNUNET_i2s (&my_identity)); - LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG, "R5N RESULT %s: %s->%s (%u)\n", - GNUNET_h2s (&prm->key), GNUNET_i2s (peer), tmp, + LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG, + "R5N RESULT %s: %s->%s (%u)\n", + GNUNET_h2s (&prm->key), + GNUNET_i2s (peer), + tmp, get_path_length + 1); GNUNET_free (tmp); } /* if we got a HELLO, consider it for our own routing table */ - if (type == GNUNET_BLOCK_TYPE_DHT_HELLO) + if (GNUNET_BLOCK_TYPE_DHT_HELLO == type) { const struct GNUNET_MessageHeader *h; struct GNUNET_PeerIdentity pid; - int bucket; /* Should be a HELLO, validate and consider using it! */ if (data_size < sizeof (struct GNUNET_MessageHeader)) @@ -2119,46 +2291,45 @@ handle_dht_p2p_result (void *cls, const struct GNUNET_PeerIdentity *peer, return GNUNET_YES; } if (GNUNET_OK != - GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) h, &pid)) + GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) h, + &pid)) { GNUNET_break_op (0); return GNUNET_YES; } - if ((GNUNET_YES != disable_try_connect) && - 0 != memcmp (&my_identity, &pid, sizeof (struct GNUNET_PeerIdentity))) - { - struct GNUNET_HashCode pid_hash; - - GNUNET_CRYPTO_hash (&pid, sizeof (struct GNUNET_PeerIdentity), &pid_hash); - bucket = find_bucket (&pid_hash); - if ((bucket >= 0) && - (k_buckets[bucket].peers_size < bucket_size) && - (NULL != GDS_transport_handle)) - { - GNUNET_TRANSPORT_offer_hello (GDS_transport_handle, h, NULL, NULL); - GNUNET_TRANSPORT_try_connect (GDS_transport_handle, &pid, NULL, NULL); /*FIXME TRY_CONNECT change */ - } - } + if ( (GNUNET_YES != disable_try_connect) && + (0 != memcmp (&my_identity, + &pid, + sizeof (struct GNUNET_PeerIdentity))) ) + try_connect (&pid, + h); } /* append 'peer' to 'get_path' */ { struct GNUNET_PeerIdentity xget_path[get_path_length + 1]; - memcpy (xget_path, get_path, + memcpy (xget_path, + get_path, get_path_length * sizeof (struct GNUNET_PeerIdentity)); xget_path[get_path_length] = *peer; get_path_length++; /* forward to local clients */ GDS_CLIENTS_handle_reply (GNUNET_TIME_absolute_ntoh (prm->expiration_time), - &prm->key, get_path_length, xget_path, - put_path_length, put_path, type, data_size, data); + &prm->key, + get_path_length, + xget_path, + put_path_length, + put_path, + type, + data_size, + data); GDS_CLIENTS_process_get_resp (type, - xget_path, get_path_length, + xget_path, + get_path_length, put_path, put_path_length, - GNUNET_TIME_absolute_ntoh ( - prm->expiration_time), + GNUNET_TIME_absolute_ntoh (prm->expiration_time), &prm->key, data, data_size); @@ -2173,13 +2344,22 @@ handle_dht_p2p_result (void *cls, const struct GNUNET_PeerIdentity *peer, GDS_DATACACHE_handle_put (GNUNET_TIME_absolute_ntoh (prm->expiration_time), &prm->key, - get_path_length + put_path_length, xput_path, - type, data_size, data); + get_path_length + put_path_length, + xput_path, + type, + data_size, + data); } /* forward to other peers */ - GDS_ROUTING_process (type, GNUNET_TIME_absolute_ntoh (prm->expiration_time), - &prm->key, put_path_length, put_path, get_path_length, - xget_path, data, data_size); + GDS_ROUTING_process (type, + GNUNET_TIME_absolute_ntoh (prm->expiration_time), + &prm->key, + put_path_length, + put_path, + get_path_length, + xget_path, + data, + data_size); } return GNUNET_YES; @@ -2189,7 +2369,7 @@ handle_dht_p2p_result (void *cls, const struct GNUNET_PeerIdentity *peer, /** * Initialize neighbours subsystem. * - * @return GNUNET_OK on success, GNUNET_SYSERR on error + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GDS_NEIGHBOURS_init () @@ -2213,14 +2393,21 @@ GDS_NEIGHBOURS_init () log_route_details_stderr = (NULL != getenv("GNUNET_DHT_ROUTE_DEBUG")) ? GNUNET_YES : GNUNET_NO; - atsAPI = GNUNET_ATS_performance_init (GDS_cfg, NULL, NULL); + ats_ch = GNUNET_ATS_connectivity_init (GDS_cfg); core_api = - GNUNET_CORE_connect (GDS_cfg, NULL, &core_init, &handle_core_connect, - &handle_core_disconnect, NULL, GNUNET_NO, NULL, - GNUNET_NO, core_handlers); + GNUNET_CORE_connect (GDS_cfg, NULL, + &core_init, + &handle_core_connect, + &handle_core_disconnect, + NULL, GNUNET_NO, + NULL, GNUNET_NO, + core_handlers); if (core_api == NULL) return GNUNET_SYSERR; - all_known_peers = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO); + all_connected_peers = GNUNET_CONTAINER_multipeermap_create (256, + GNUNET_NO); + all_desired_peers = GNUNET_CONTAINER_multipeermap_create (256, + GNUNET_NO); return GNUNET_OK; } @@ -2235,11 +2422,16 @@ GDS_NEIGHBOURS_done () return; GNUNET_CORE_disconnect (core_api); core_api = NULL; - GNUNET_ATS_performance_done (atsAPI); - atsAPI = NULL; - GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (all_known_peers)); - GNUNET_CONTAINER_multipeermap_destroy (all_known_peers); - all_known_peers = NULL; + GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (all_connected_peers)); + GNUNET_CONTAINER_multipeermap_destroy (all_connected_peers); + all_connected_peers = NULL; + GNUNET_CONTAINER_multipeermap_iterate (all_desired_peers, + &free_connect_info, + NULL); + GNUNET_CONTAINER_multipeermap_destroy (all_desired_peers); + all_desired_peers = NULL; + GNUNET_ATS_connectivity_done (ats_ch); + ats_ch = NULL; if (NULL != find_peer_task) { GNUNET_SCHEDULER_cancel (find_peer_task); @@ -2247,6 +2439,7 @@ GDS_NEIGHBOURS_done () } } + /** * Get the ID of the local node. *