From 1f3e06a9d063aefd82ff5081f340a3ce5783ca9b Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 27 Sep 2011 12:46:48 +0000 Subject: [PATCH] process find peer requests and replies --- src/dht/Makefile.am | 1 + src/dht/gnunet-service-dht-new.c | 23 +- src/dht/gnunet-service-dht.h | 4 + src/dht/gnunet-service-dht_neighbours.c | 200 +++++++++++++++--- src/dht/gnunet-service-dht_routing.c | 21 +- src/include/gnunet_constants.h | 8 + src/include/gnunet_peerinfo_service.h | 4 +- src/transport/gnunet-service-transport.c | 2 +- .../gnunet-service-transport_hello.c | 3 +- .../gnunet-service-transport_hello.h | 7 - 10 files changed, 219 insertions(+), 54 deletions(-) diff --git a/src/dht/Makefile.am b/src/dht/Makefile.am index 3d30f98d7..274a89b18 100644 --- a/src/dht/Makefile.am +++ b/src/dht/Makefile.am @@ -128,6 +128,7 @@ gnunet_service_dht_new_LDADD = \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/nse/libgnunetnse.la \ $(top_builddir)/src/transport/libgnunettransport.la \ + $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/block/libgnunetblock.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ diff --git a/src/dht/gnunet-service-dht-new.c b/src/dht/gnunet-service-dht-new.c index e4ea3891b..766c6c0a9 100644 --- a/src/dht/gnunet-service-dht-new.c +++ b/src/dht/gnunet-service-dht-new.c @@ -60,16 +60,17 @@ const struct GNUNET_CONFIGURATION_Handle *GDS_cfg; */ struct GNUNET_MessageHeader *GDS_my_hello; - /** - * Handle to get our current HELLO. + * Handle to the transport service, for getting our hello */ -static struct GNUNET_TRANSPORT_GetHelloHandle *ghh; +struct GNUNET_TRANSPORT_Handle *GDS_transport_handle; + + /** - * Handle to the transport service, for getting our hello + * Handle to get our current HELLO. */ -static struct GNUNET_TRANSPORT_Handle *transport_handle; +static struct GNUNET_TRANSPORT_GetHelloHandle *ghh; /** @@ -104,10 +105,10 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_TRANSPORT_get_hello_cancel (ghh); ghh = NULL; } - if (transport_handle != NULL) + if (GDS_transport_handle != NULL) { - GNUNET_TRANSPORT_disconnect (transport_handle); - transport_handle = NULL; + GNUNET_TRANSPORT_disconnect (GDS_transport_handle); + GDS_transport_handle = NULL; } GDS_NEIGHBOURS_done (); GDS_DATACACHE_done (); @@ -155,15 +156,15 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, } GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); - transport_handle = + GDS_transport_handle = GNUNET_TRANSPORT_connect (GDS_cfg, NULL, NULL, NULL, NULL, NULL); - if (transport_handle == NULL) + if (GDS_transport_handle == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to connect to transport service!\n")); return; } - ghh = GNUNET_TRANSPORT_get_hello (transport_handle, + ghh = GNUNET_TRANSPORT_get_hello (GDS_transport_handle, &process_hello, NULL); } diff --git a/src/dht/gnunet-service-dht.h b/src/dht/gnunet-service-dht.h index cacc00971..3a716acde 100644 --- a/src/dht/gnunet-service-dht.h +++ b/src/dht/gnunet-service-dht.h @@ -50,5 +50,9 @@ extern struct GNUNET_STATISTICS_Handle *GDS_stats; */ extern struct GNUNET_MessageHeader *GDS_my_hello; +/** + * Handle to the transport service, for getting our hello + */ +extern struct GNUNET_TRANSPORT_Handle *GDS_transport_handle; #endif diff --git a/src/dht/gnunet-service-dht_neighbours.c b/src/dht/gnunet-service-dht_neighbours.c index f9e31310e..705168b17 100644 --- a/src/dht/gnunet-service-dht_neighbours.c +++ b/src/dht/gnunet-service-dht_neighbours.c @@ -28,6 +28,7 @@ #include "platform.h" #include "gnunet_block_lib.h" #include "gnunet_util_lib.h" +#include "gnunet_hello_lib.h" #include "gnunet_constants.h" #include "gnunet_protocols.h" #include "gnunet_nse_service.h" @@ -37,6 +38,7 @@ #include "gnunet_hello_lib.h" #include "gnunet_dht_service.h" #include "gnunet_statistics_service.h" +#include "gnunet_peerinfo_service.h" #include "dht.h" #include "gnunet-service-dht.h" #include "gnunet-service-dht_clients.h" @@ -326,9 +328,10 @@ struct PeerInfo struct GNUNET_CORE_InformationRequestContext *info_ctx; /** - * Task for scheduling message sends. + * HELLO message for the peer, NULL if not known. FIXME: track + * separately? FIXME: free!? */ - GNUNET_SCHEDULER_TaskIdentifier send_task; + struct GNUNET_HELLO_Message *hello; /** * Task for scheduling preference updates @@ -418,6 +421,11 @@ static struct GNUNET_PeerIdentity my_identity; */ static struct GNUNET_CORE_Handle *coreAPI; +/** + * Handle for peerinfo notifications. + */ +static struct GNUNET_PEERINFO_NotifyContext *pnc; + /** * Find the optimal bucket for this key. @@ -1510,6 +1518,81 @@ handle_dht_p2p_put (void *cls, } +/** + * We have received a FIND PEER request. Send matching + * HELLOs back. + * + * @param sender sender of the FIND PEER request + * @param key peers close to this key are desired + * @param bf peers matching this bf are excluded + * @param bf_mutator mutator for bf + */ +static void +handle_find_peer (const struct GNUNET_PeerIdentity *sender, + const GNUNET_HashCode *key, + struct GNUNET_CONTAINER_BloomFilter *bf, + uint32_t bf_mutator) +{ + int bucket_idx; + struct PeerBucket *bucket; + struct PeerInfo *peer; + unsigned int choice; + GNUNET_HashCode mhash; + + /* first, check about our own HELLO */ + if (NULL != GDS_my_hello) + { + GNUNET_BLOCK_mingle_hash (&my_identity.hashPubKey, bf_mutator, &mhash); + if (GNUNET_YES != GNUNET_CONTAINER_bloomfilter_test (bf, &mhash)) + + GDS_NEIGHBOURS_handle_reply (sender, + GNUNET_BLOCK_TYPE_DHT_HELLO, + GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION), + key, + 0, NULL, + 0, NULL, + GDS_my_hello, + GNUNET_HELLO_size ((const struct GNUNET_HELLO_Message*) GDS_my_hello)); + } + + /* then, also consider sending a random HELLO from the closest bucket */ + bucket_idx = find_bucket (key); + if (bucket_idx == GNUNET_SYSERR) + return; + bucket = &k_buckets[bucket_idx]; + if (bucket->peers_size == 0) + return; + choice = GNUNET_CRYPTO_random_u32 (bucket->peers_size, + GNUNET_CRYPTO_QUALITY_WEAK); + peer = bucket->head; + while (choice > 0) + { + GNUNET_assert (peer != NULL); + peer = peer->next; + } + choice = bucket->peers_size; + do + { + peer = peer->next; + if (choice-- == 0) + return; /* no non-masked peer available */ + if (peer == NULL) + peer = bucket->head; + GNUNET_BLOCK_mingle_hash (&peer->id.hashPubKey, bf_mutator, &mhash); + } + while ( (peer->hello == NULL) || + (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (bf, &mhash)) ); + GDS_NEIGHBOURS_handle_reply (sender, + GNUNET_BLOCK_TYPE_DHT_HELLO, + GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION), + key, + 0, NULL, + 0, NULL, + peer->hello, + GNUNET_HELLO_size (peer->hello)); +} + + /** * Core handler for p2p get requests. * @@ -1588,19 +1671,30 @@ handle_dht_p2p_get (void *cls, const struct GNUNET_PeerIdentity *peer, &get->key, xquery, xquery_size, reply_bf, get->bf_mutator); - /* FIXME: check options (find peer, local-processing-only-if-nearest, etc.!) */ /* local lookup (this may update the reply_bf) */ if ( (0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) || (am_closest_peer (&get->key, peer_bf) ) ) - GDS_DATACACHE_handle_get (&get->key, - type, - xquery, xquery_size, - &reply_bf, - get->bf_mutator); - /* FIXME: should track if the local lookup resulted in a - definitive result and then NOT do P2P forwarding */ + { + if ( (0 != (options & GNUNET_DHT_RO_FIND_PEER))) + { + handle_find_peer (peer, + &get->key, + reply_bf, + get->bf_mutator); + } + else + { + GDS_DATACACHE_handle_get (&get->key, + type, + xquery, xquery_size, + &reply_bf, + get->bf_mutator); + /* FIXME: should track if the local lookup resulted in a + definitive result and then NOT do P2P forwarding */ + } + } /* P2P forwarding */ GDS_NEIGHBOURS_handle_get (type, @@ -1669,6 +1763,44 @@ handle_dht_p2p_result (void *cls, const struct GNUNET_PeerIdentity *peer, data = (const void*) &get_path[get_path_length]; data_size = msize - (sizeof (struct PeerResultMessage) + (get_path_length + put_path_length) * sizeof (struct GNUNET_PeerIdentity)); + if (type == GNUNET_BLOCK_TYPE_DHT_HELLO) + { + 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)) + { + GNUNET_break_op (0); + return GNUNET_YES; + } + h = data; + if (data_size != ntohs (h->size)) + { + GNUNET_break_op (0); + return GNUNET_YES; + } + if (GNUNET_OK != + GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message*) h, + &pid)) + { + GNUNET_break_op (0); + return GNUNET_YES; + } + bucket = find_bucket (&pid.hashPubKey); + if ( (bucket >= 0) && + (k_buckets[bucket].peers_size < bucket_size) ) + { + if (NULL != GDS_transport_handle) + GNUNET_TRANSPORT_offer_hello (GDS_transport_handle, + h, NULL, NULL); + (void) GNUNET_CORE_peer_request_connect (coreAPI, + &pid, + NULL, NULL); + } + } + /* append 'peer' to 'get_path' */ { struct GNUNET_PeerIdentity xget_path[get_path_length+1]; @@ -1703,6 +1835,25 @@ handle_dht_p2p_result (void *cls, const struct GNUNET_PeerIdentity *peer, } +/** + * Function called for each HELLO known to PEERINFO. + * + * @param cls closure + * @param peer id of the peer, NULL for last call + * @param hello hello message for the peer (can be NULL) + * @param error message + */ +static void +process_hello (void *cls, + const struct GNUNET_PeerIdentity * + peer, + const struct GNUNET_HELLO_Message * + hello, const char *err_msg) +{ + // FIXME: track HELLOs, possibly ask core to establish connections +} + + /** * Initialize neighbours subsystem. * @@ -1736,20 +1887,9 @@ GDS_NEIGHBOURS_init () if (coreAPI == NULL) return GNUNET_SYSERR; all_known_peers = GNUNET_CONTAINER_multihashmap_create (256); -#if 0 - struct GNUNET_TIME_Relative next_send_time; - - // FIXME! - next_send_time.rel_value = - DHT_MINIMUM_FIND_PEER_INTERVAL.rel_value + - GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, - (DHT_MAXIMUM_FIND_PEER_INTERVAL.rel_value / - 2) - - DHT_MINIMUM_FIND_PEER_INTERVAL.rel_value); - find_peer_task = GNUNET_SCHEDULER_add_delayed (next_send_time, - &send_find_peer_message, - &find_peer_context); -#endif + pnc = GNUNET_PEERINFO_notify (GDS_cfg, + &process_hello, + NULL); return GNUNET_OK; } @@ -1762,6 +1902,11 @@ GDS_NEIGHBOURS_done () { if (coreAPI == NULL) return; + if (NULL != pnc) + { + GNUNET_PEERINFO_notify_cancel (pnc); + pnc = NULL; + } GNUNET_CORE_disconnect (coreAPI); coreAPI = NULL; GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (all_known_peers)); @@ -1776,10 +1921,3 @@ GDS_NEIGHBOURS_done () /* end of gnunet-service-dht_neighbours.c */ - - -#if 0 - - - -#endif diff --git a/src/dht/gnunet-service-dht_routing.c b/src/dht/gnunet-service-dht_routing.c index 41996d654..5a87f8b32 100644 --- a/src/dht/gnunet-service-dht_routing.c +++ b/src/dht/gnunet-service-dht_routing.c @@ -169,6 +169,8 @@ process (void *cls, enum GNUNET_BLOCK_EvaluationResult eval; unsigned int gpl; unsigned int ppl; + GNUNET_HashCode hc; + const GNUNET_HashCode *eval_key; if ( (rr->type != GNUNET_BLOCK_TYPE_ANY) && (rr->type != pc->type) ) @@ -184,9 +186,26 @@ process (void *cls, gpl = 0; ppl = 0; } + if ( (0 != (rr->options & GNUNET_DHT_RO_FIND_PEER)) && + (pc->type == GNUNET_BLOCK_TYPE_DHT_HELLO) ) + { + /* key may not match HELLO, which is OK since + the search is approximate. Still, the evaluation + would fail since the match is not exact. So + we fake it by changing the key to the actual PID ... */ + GNUNET_BLOCK_get_key (GDS_block_context, + GNUNET_BLOCK_TYPE_DHT_HELLO, + pc->data, pc->data_size, + &hc); + eval_key = &hc; + } + else + { + eval_key = key; + } eval = GNUNET_BLOCK_evaluate (GDS_block_context, pc->type, - key, + eval_key, &rr->reply_bf, rr->reply_bf_mutator, rr->xquery, diff --git a/src/include/gnunet_constants.h b/src/include/gnunet_constants.h index 7315c9c73..0fc63a526 100644 --- a/src/include/gnunet_constants.h +++ b/src/include/gnunet_constants.h @@ -97,6 +97,14 @@ extern "C" */ #define GNUNET_CONSTANTS_IDLE_LOAD_THRESHOLD 70 +/** + * After how long do we expire an address in a HELLO that we just + * validated? This value is also used for our own addresses when we + * create a HELLO. + */ +#define GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 12) + + /** * Size of the 'struct EncryptedMessage' of the core (which * is the per-message overhead of the core). diff --git a/src/include/gnunet_peerinfo_service.h b/src/include/gnunet_peerinfo_service.h index 158eae602..12264fb1f 100644 --- a/src/include/gnunet_peerinfo_service.h +++ b/src/include/gnunet_peerinfo_service.h @@ -111,8 +111,8 @@ struct GNUNET_PEERINFO_IteratorContext; /** - * Call a method for each known matching host and change its trust - * value. The callback method will be invoked once for each matching + * Call a method for each known matching host to get its HELLO. + * The callback method will be invoked once for each matching * host and then finally once with a NULL pointer. After that final * invocation, the iterator context must no longer be used. * diff --git a/src/transport/gnunet-service-transport.c b/src/transport/gnunet-service-transport.c index d8733fbb3..537f99dcf 100644 --- a/src/transport/gnunet-service-transport.c +++ b/src/transport/gnunet-service-transport.c @@ -92,7 +92,7 @@ transmit_our_hello (void *cls, const struct GNUNET_PeerIdentity *target, const struct GNUNET_MessageHeader *hello = cls; GST_neighbours_send (target, (const char *) hello, ntohs (hello->size), - GST_HELLO_ADDRESS_EXPIRATION, NULL, NULL); + GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION, NULL, NULL); } diff --git a/src/transport/gnunet-service-transport_hello.c b/src/transport/gnunet-service-transport_hello.c index 2793ce5eb..a1c721857 100644 --- a/src/transport/gnunet-service-transport_hello.c +++ b/src/transport/gnunet-service-transport_hello.c @@ -24,6 +24,7 @@ * @author Christian Grothoff */ #include "platform.h" +#include "gnunet_constants.h" #include "gnunet_hello_lib.h" #include "gnunet_peerinfo_service.h" #include "gnunet_statistics_service.h" @@ -165,7 +166,7 @@ refresh_hello_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) hello_task = GNUNET_SCHEDULER_NO_TASK; gc.addr_pos = oal_head; gc.expiration = - GNUNET_TIME_relative_to_absolute (GST_HELLO_ADDRESS_EXPIRATION); + GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION); GNUNET_free (our_hello); our_hello = GNUNET_HELLO_create (&GST_my_public_key, &address_generator, &gc); #if DEBUG_TRANSPORT diff --git a/src/transport/gnunet-service-transport_hello.h b/src/transport/gnunet-service-transport_hello.h index 153b7447e..8d15ec6b5 100644 --- a/src/transport/gnunet-service-transport_hello.h +++ b/src/transport/gnunet-service-transport_hello.h @@ -31,13 +31,6 @@ #include "gnunet_util_lib.h" -/** - * After how long do we expire an address in a HELLO that we just - * validated? This value is also used for our own addresses when we - * create a HELLO. - */ -#define GST_HELLO_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 12) - /** * Signature of a function to call whenever our hello changes. -- 2.25.1