X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Ftransport%2Fgnunet-service-transport_validation.c;h=314eefaec2fb7d25dd7a80ab0b8d9373ea7b4f55;hb=f0a8d26b26cda04518e3555373172f6b4940e489;hp=3c7edd140333c427de4829753fe89af83c3aadb8;hpb=c123f267c0a83f69395e09a6034d5cc219ade838;p=oweals%2Fgnunet.git diff --git a/src/transport/gnunet-service-transport_validation.c b/src/transport/gnunet-service-transport_validation.c index 3c7edd140..314eefaec 100644 --- a/src/transport/gnunet-service-transport_validation.c +++ b/src/transport/gnunet-service-transport_validation.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2010-2014 Christian Grothoff (and other contributing authors) + Copyright (C) 2010-2015 Christian Grothoff (and other contributing authors) 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. */ /** @@ -24,12 +24,13 @@ * @author Christian Grothoff */ #include "platform.h" +#include "gnunet-service-transport_ats.h" +#include "gnunet-service-transport_blacklist.h" #include "gnunet-service-transport_clients.h" -#include "gnunet-service-transport_validation.h" -#include "gnunet-service-transport_plugins.h" #include "gnunet-service-transport_hello.h" -#include "gnunet-service-transport_blacklist.h" #include "gnunet-service-transport_neighbours.h" +#include "gnunet-service-transport_plugins.h" +#include "gnunet-service-transport_validation.h" #include "gnunet-service-transport.h" #include "gnunet_hello_lib.h" #include "gnunet_ats_service.h" @@ -188,16 +189,6 @@ struct ValidationEntry */ struct GST_BlacklistCheck *bc; - /** - * Public key of the peer. - */ - struct GNUNET_CRYPTO_EddsaPublicKey public_key; - - /** - * The identity of the peer. FIXME: duplicated (also in 'address') - */ - struct GNUNET_PeerIdentity pid; - /** * Cached PONG signature */ @@ -206,12 +197,12 @@ struct ValidationEntry /** * ID of task that will clean up this entry if nothing happens. */ - GNUNET_SCHEDULER_TaskIdentifier timeout_task; + struct GNUNET_SCHEDULER_Task *timeout_task; /** * ID of task that will trigger address revalidation. */ - GNUNET_SCHEDULER_TaskIdentifier revalidation_task; + struct GNUNET_SCHEDULER_Task *revalidation_task; /** * At what time did we send the latest validation request (PING)? @@ -253,13 +244,14 @@ struct ValidationEntry * Current state of this validation entry */ enum GNUNET_TRANSPORT_ValidationState state; + /** * Challenge number we used. */ uint32_t challenge; /** - * When passing the address in 'add_valid_peer_address', did we + * When passing the address in #add_valid_peer_address(), did we * copy the address to the HELLO yet? */ int copied; @@ -274,45 +266,18 @@ struct ValidationEntry */ int expecting_pong; - enum GNUNET_ATS_Network_Type network; -}; - - -/** - * Context of currently active requests to peerinfo - * for validation of HELLOs. - */ -struct CheckHelloValidatedContext -{ - - /** - * This is a doubly-linked list. - */ - struct CheckHelloValidatedContext *next; - /** - * This is a doubly-linked list. + * Is this address known to ATS as valid right now? */ - struct CheckHelloValidatedContext *prev; + int known_to_ats; /** - * Hello that we are validating. + * Which network type does our address belong to? */ - const struct GNUNET_HELLO_Message *hello; - + enum GNUNET_ATS_Network_Type network; }; -/** - * Head of linked list of HELLOs awaiting validation. - */ -static struct CheckHelloValidatedContext *chvc_head; - -/** - * Tail of linked list of HELLOs awaiting validation - */ -static struct CheckHelloValidatedContext *chvc_tail; - /** * Map of PeerIdentities to 'struct ValidationEntry*'s (addresses * of the given peer that we are currently validating, have validated @@ -331,7 +296,9 @@ static struct GNUNET_PEERINFO_NotifyContext *pnc; static struct GNUNET_TIME_Relative validation_delay; /** - * Number of validations running + * Number of validations running; any PING that was not yet + * matched by a PONG and for which we have not yet hit the + * timeout is considered a running 'validation'. */ static unsigned int validations_running; @@ -364,6 +331,21 @@ struct ValidationEntryMatchContext }; +/** + * Provide an update on the `validation_map` map size to statistics. + * This function should be called whenever the `validation_map` + * is changed. + */ +static void +publish_ve_stat_update () +{ + GNUNET_STATISTICS_set (GST_stats, + gettext_noop ("# Addresses in validation map"), + GNUNET_CONTAINER_multipeermap_size (validation_map), + GNUNET_NO); +} + + /** * Iterate over validation entries until a matching one is found. * @@ -381,7 +363,8 @@ validation_entry_match (void *cls, struct ValidationEntryMatchContext *vemc = cls; struct ValidationEntry *ve = value; - if (0 == GNUNET_HELLO_address_cmp (ve->address, vemc->address)) + if (0 == GNUNET_HELLO_address_cmp (ve->address, + vemc->address)) { vemc->ve = ve; return GNUNET_NO; @@ -402,7 +385,7 @@ validation_entry_changed (struct ValidationEntry *ve, enum GNUNET_TRANSPORT_ValidationState state) { ve->state = state; - GST_clients_broadcast_validation_notification (&ve->pid, + GST_clients_broadcast_validation_notification (&ve->address->peer, ve->address, ve->send_time, ve->valid_until, @@ -426,11 +409,12 @@ cleanup_validation_entry (void *cls, { struct ValidationEntry *ve = value; - ve->next_validation = GNUNET_TIME_absolute_get_zero_(); + ve->next_validation = GNUNET_TIME_UNIT_ZERO_ABS; ve->valid_until = GNUNET_TIME_UNIT_ZERO_ABS; /* Notify about deleted entry */ - validation_entry_changed (ve, GNUNET_TRANSPORT_VS_REMOVE); + validation_entry_changed (ve, + GNUNET_TRANSPORT_VS_REMOVE); if (NULL != ve->bc) { @@ -439,25 +423,33 @@ cleanup_validation_entry (void *cls, } GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multipeermap_remove (validation_map, - &ve->pid, ve)); + &ve->address->peer, + ve)); + publish_ve_stat_update (); + if (GNUNET_YES == ve->known_to_ats) + { + GST_ats_expire_address (ve->address); + ve->known_to_ats = GNUNET_NO; + } GNUNET_HELLO_address_free (ve->address); - if (GNUNET_SCHEDULER_NO_TASK != ve->timeout_task) + if (NULL != ve->timeout_task) { GNUNET_SCHEDULER_cancel (ve->timeout_task); - ve->timeout_task = GNUNET_SCHEDULER_NO_TASK; + ve->timeout_task = NULL; } - if (GNUNET_SCHEDULER_NO_TASK != ve->revalidation_task) + if (NULL != ve->revalidation_task) { GNUNET_SCHEDULER_cancel (ve->revalidation_task); - ve->revalidation_task = GNUNET_SCHEDULER_NO_TASK; + ve->revalidation_task = NULL; } - if ((GNUNET_YES == ve->expecting_pong) && - (validations_running > 0)) + if ( (GNUNET_YES == ve->expecting_pong) && + (validations_running > 0) ) { - validations_running --; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Validation finished, %u validation processes running\n", - validations_running); + validations_running--; + GNUNET_STATISTICS_set (GST_stats, + gettext_noop ("# validations running"), + validations_running, + GNUNET_NO); } GNUNET_free (ve); return GNUNET_OK; @@ -468,7 +460,7 @@ cleanup_validation_entry (void *cls, * Address validation cleanup task. Assesses if the record is no * longer valid and then possibly triggers its removal. * - * @param cls the 'struct ValidationEntry' + * @param cls the `struct ValidationEntry` * @param tc scheduler context (unused) */ static void @@ -479,20 +471,31 @@ timeout_hello_validation (void *cls, struct GNUNET_TIME_Absolute max; struct GNUNET_TIME_Relative left; - ve->timeout_task = GNUNET_SCHEDULER_NO_TASK; - max = GNUNET_TIME_absolute_max (ve->valid_until, ve->revalidation_block); + ve->timeout_task = NULL; + /* For valid addresses, we want to wait until the expire; + for addresses under PING validation, we want to wait + until we give up on the PING */ + max = GNUNET_TIME_absolute_max (ve->valid_until, + ve->revalidation_block); left = GNUNET_TIME_absolute_get_remaining (max); if (left.rel_value_us > 0) { - /* should wait a bit longer */ + /* We should wait a bit longer. This happens when + address lifetimes are extended due to successful + validations. */ ve->timeout_task = - GNUNET_SCHEDULER_add_delayed (left, &timeout_hello_validation, ve); + GNUNET_SCHEDULER_add_delayed (left, + &timeout_hello_validation, + ve); return; } GNUNET_STATISTICS_update (GST_stats, - gettext_noop ("# address records discarded"), 1, + gettext_noop ("# address records discarded (timeout)"), + 1, GNUNET_NO); - cleanup_validation_entry (NULL, &ve->pid, ve); + cleanup_validation_entry (NULL, + &ve->address->peer, + ve); } @@ -500,13 +503,19 @@ timeout_hello_validation (void *cls, * Function called with the result from blacklisting. * Send a PING to the other peer if a communication is allowed. * - * @param cls our 'struct ValidationEntry' + * @param cls our `struct ValidationEntry` * @param pid identity of the other peer - * @param result #GNUNET_OK if the connection is allowed, #GNUNET_NO if not + * @param address_null address associated with the request, always NULL + * @param session_null session associated with the request, always NULL + * @param result #GNUNET_OK if the connection is allowed, + * #GNUNET_NO if not, + * #GNUNET_SYSERR if operation was aborted */ static void transmit_ping_if_allowed (void *cls, const struct GNUNET_PeerIdentity *pid, + const struct GNUNET_HELLO_Address *address_null, + struct Session *session_null, int result) { struct ValidationEntry *ve = cls; @@ -514,40 +523,35 @@ transmit_ping_if_allowed (void *cls, struct GNUNET_TRANSPORT_PluginFunctions *papi; struct GNUNET_TIME_Absolute next; const struct GNUNET_MessageHeader *hello; - enum GNUNET_ATS_Network_Type network; ssize_t ret; size_t tsize; size_t slen; uint16_t hsize; + struct Session *session; ve->bc = NULL; - if (GNUNET_NO == result) + if (GNUNET_OK != result) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Blacklist denies to send PING to `%s' `%s' `%s'\n", + "Blacklist denies sending PING to `%s' `%s' `%s'\n", GNUNET_i2s (pid), GST_plugins_a2s (ve->address), ve->address->transport_name); + GNUNET_STATISTICS_update (GST_stats, + gettext_noop ("# address records discarded (blacklist)"), + 1, + GNUNET_NO); + cleanup_validation_entry (NULL, + pid, + ve); return; } - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Transmitting plain PING to `%s' `%s' `%s'\n", - GNUNET_i2s (pid), - GST_plugins_a2s (ve->address), - ve->address->transport_name); - - next = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(), - validation_delay); - if (next.abs_value_us > validation_next.abs_value_us) - validation_next = next; /* We're going to send a PING so delay next validation */ - - slen = strlen (ve->address->transport_name) + 1; hello = GST_hello_get (); + GNUNET_assert (NULL != hello); + slen = strlen (ve->address->transport_name) + 1; hsize = ntohs (hello->size); - tsize = - sizeof (struct TransportPingMessage) + ve->address->address_length + - slen + hsize; + tsize = sizeof (struct TransportPingMessage) + + ve->address->address_length + slen + hsize; ping.header.size = htons (sizeof (struct TransportPingMessage) + @@ -558,80 +562,86 @@ transmit_ping_if_allowed (void *cls, if (tsize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _ - ("Not transmitting `%s' with `%s', message too big (%u bytes!). This should not happen.\n"), - "HELLO", "PING", (unsigned int) tsize); - /* message too big (!?), get rid of HELLO */ + GNUNET_break (0); hsize = 0; tsize = sizeof (struct TransportPingMessage) + ve->address->address_length + slen + hsize; } { - char message_buf[tsize]; - - /* build message with structure: - * [HELLO][TransportPingMessage][Transport name][Address] */ - memcpy (message_buf, hello, hsize); - memcpy (&message_buf[hsize], &ping, sizeof (struct TransportPingMessage)); + char message_buf[tsize] GNUNET_ALIGN; + + memcpy (message_buf, + hello, + hsize); + memcpy (&message_buf[hsize], + &ping, + sizeof (struct TransportPingMessage)); memcpy (&message_buf[sizeof (struct TransportPingMessage) + hsize], - ve->address->transport_name, slen); + ve->address->transport_name, + slen); memcpy (&message_buf[sizeof (struct TransportPingMessage) + slen + hsize], - ve->address->address, ve->address->address_length); + ve->address->address, + ve->address->address_length); papi = GST_plugins_find (ve->address->transport_name); - if (papi == NULL) - ret = -1; - else + GNUNET_assert (NULL != papi); + session = papi->get_session (papi->cls, + ve->address); + if (NULL == session) { - GNUNET_assert (NULL != papi->send); - GNUNET_assert (NULL != papi->get_session); - struct Session * session = papi->get_session(papi->cls, ve->address); - - if (session != NULL) - { - ret = papi->send (papi->cls, session, - message_buf, tsize, - PING_PRIORITY, ACCEPTABLE_PING_DELAY, - NULL, NULL); - network = papi->get_network (papi->cls, session); - if (GNUNET_ATS_NET_UNSPECIFIED == network) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Could not obtain a valid network for `%s' `%s'\n", - GNUNET_i2s (pid), - GST_plugins_a2s (ve->address)); - GNUNET_break(0); - } - GST_neighbours_notify_data_sent (pid, ve->address, session, tsize); - } - else - { - /* Could not get a valid session */ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Could not get a valid session for `%s' `%s'\n", - GNUNET_i2s (pid), - GST_plugins_a2s (ve->address)); - ret = -1; - } + /* Could not get a valid session */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Failed to get session to send PING to `%s' at `%s'\n", + GNUNET_i2s (pid), + GST_plugins_a2s (ve->address)); + return; } - } - if (-1 != ret) - { + + ret = papi->send (papi->cls, session, + message_buf, tsize, + PING_PRIORITY, + ACCEPTABLE_PING_DELAY, + NULL, NULL); + if (-1 == ret) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Failed to send PING to `%s' at `%s'\n", + GNUNET_i2s (pid), + GST_plugins_a2s (ve->address)); + return; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Transmitted plain PING to `%s' `%s' `%s'\n", + GNUNET_i2s (pid), + GST_plugins_a2s (ve->address), + ve->address->transport_name); + ve->network = papi->get_network (papi->cls, + session); + GNUNET_break (GNUNET_ATS_NET_UNSPECIFIED != ve->network); + GST_neighbours_notify_data_sent (ve->address, + session, + tsize); + next = GNUNET_TIME_relative_to_absolute (validation_delay); + validation_next = GNUNET_TIME_absolute_max (next, + validation_next); ve->send_time = GNUNET_TIME_absolute_get (); GNUNET_STATISTICS_update (GST_stats, - gettext_noop - ("# PING without HELLO messages sent"), 1, + gettext_noop ("# PINGs for address validation sent"), + 1, GNUNET_NO); - - ve->network = network; ve->expecting_pong = GNUNET_YES; validations_running++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Validation started, %u validation processes running\n", validations_running); + GNUNET_STATISTICS_set (GST_stats, + gettext_noop ("# validations running"), + validations_running, + GNUNET_NO); /* Notify about PING sent */ - validation_entry_changed (ve, GNUNET_TRANSPORT_VS_UPDATE); + validation_entry_changed (ve, + GNUNET_TRANSPORT_VS_UPDATE); + } } @@ -639,7 +649,7 @@ transmit_ping_if_allowed (void *cls, /** * Do address validation again to keep address valid. * - * @param cls the 'struct ValidationEntry' + * @param cls the `struct ValidationEntry` * @param tc scheduler context (unused) */ static void @@ -653,38 +663,43 @@ revalidate_address (void *cls, struct GST_BlacklistCheck *bc; uint32_t rdelay; - ve->revalidation_task = GNUNET_SCHEDULER_NO_TASK; + ve->revalidation_task = NULL; delay = GNUNET_TIME_absolute_get_remaining (ve->revalidation_block); - /* How long until we can possibly permit the next PING? */ + /* Considering current connectivity situation, what is the maximum + block period permitted? */ if (GNUNET_YES == ve->in_use) canonical_delay = CONNECTED_PING_FREQUENCY; else if (GNUNET_TIME_absolute_get_remaining (ve->valid_until).rel_value_us > 0) canonical_delay = VALIDATED_PING_FREQUENCY; else canonical_delay = UNVALIDATED_PING_KEEPALIVE; - - if (delay.rel_value_us > canonical_delay.rel_value_us * 2) - { - /* situation changed, recalculate delay */ - delay = canonical_delay; - ve->revalidation_block = GNUNET_TIME_relative_to_absolute (delay); - } + /* Use delay that is MIN of original delay and possibly adjusted + new maximum delay (which may be lower); the real delay + is originally randomized between "canonical_delay" and "2 * canonical_delay", + so continue to permit that window for the operation. */ + delay = GNUNET_TIME_relative_min (delay, + GNUNET_TIME_relative_multiply (canonical_delay, + 2)); + ve->revalidation_block = GNUNET_TIME_relative_to_absolute (delay); if (delay.rel_value_us > 0) { /* should wait a bit longer */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Waiting for %s longer before validating address `%s'\n", + "Waiting for %s longer before (re)validating address `%s'\n", GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES), GST_plugins_a2s (ve->address)); ve->revalidation_task = - GNUNET_SCHEDULER_add_delayed (delay, &revalidate_address, ve); - ve->next_validation = GNUNET_TIME_absolute_add(GNUNET_TIME_absolute_get(), delay); + GNUNET_SCHEDULER_add_delayed (delay, + &revalidate_address, ve); + ve->next_validation = GNUNET_TIME_relative_to_absolute (delay); return; } - blocked_for = GNUNET_TIME_absolute_get_remaining(validation_next); - if ((validations_running > validations_fast_start_threshold) && - (blocked_for.rel_value_us > 0)) + /* check if globally we have too many active validations at a + too high rate, if so, delay ours */ + blocked_for = GNUNET_TIME_absolute_get_remaining (validation_next); + if ( (validations_running > validations_fast_start_threshold) && + (blocked_for.rel_value_us > 0) ) { /* Validations are blocked, have to wait for blocked_for time */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, @@ -692,13 +707,21 @@ revalidate_address (void *cls, GNUNET_STRINGS_relative_time_to_string (blocked_for, GNUNET_YES), GST_plugins_a2s (ve->address)); + GNUNET_STATISTICS_update (GST_stats, + gettext_noop ("# validations delayed by global throttle"), + 1, + GNUNET_NO); ve->revalidation_task = - GNUNET_SCHEDULER_add_delayed (blocked_for, &revalidate_address, ve); - ve->next_validation = GNUNET_TIME_absolute_add(GNUNET_TIME_absolute_get(), blocked_for); + GNUNET_SCHEDULER_add_delayed (blocked_for, + &revalidate_address, + ve); + ve->next_validation = GNUNET_TIME_relative_to_absolute (blocked_for); return; } - ve->revalidation_block = GNUNET_TIME_relative_to_absolute (canonical_delay); + /* We are good to go; remember to not go again for `canonical_delay` time; + add up to `canonical_delay` to randomize start time */ + ve->revalidation_block = GNUNET_TIME_relative_to_absolute (canonical_delay); /* schedule next PINGing with some extra random delay to avoid synchronous re-validations */ rdelay = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, @@ -706,7 +729,8 @@ revalidate_address (void *cls, delay = GNUNET_TIME_relative_add (canonical_delay, GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_MICROSECONDS, rdelay)); + (GNUNET_TIME_UNIT_MICROSECONDS, + rdelay)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Validating now, next scheduled for %s, now validating address `%s'\n", @@ -714,15 +738,21 @@ revalidate_address (void *cls, GNUNET_YES), GST_plugins_a2s (ve->address)); ve->revalidation_task = - GNUNET_SCHEDULER_add_delayed (delay, &revalidate_address, ve); - ve->next_validation = GNUNET_TIME_absolute_add(GNUNET_TIME_absolute_get(), delay); + GNUNET_SCHEDULER_add_delayed (delay, + &revalidate_address, + ve); + ve->next_validation = GNUNET_TIME_relative_to_absolute (delay); /* start PINGing by checking blacklist */ GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# address revalidations started"), 1, GNUNET_NO); - bc = GST_blacklist_test_allowed (&ve->pid, ve->address->transport_name, - &transmit_ping_if_allowed, ve); + bc = GST_blacklist_test_allowed (&ve->address->peer, + ve->address->transport_name, + &transmit_ping_if_allowed, + ve, + NULL, + NULL); if (NULL != bc) ve->bc = bc; /* only set 'bc' if 'transmit_ping_if_allowed' was not already * called... */ @@ -734,14 +764,12 @@ revalidate_address (void *cls, * the given address and transport. If none exists, create one (but * without starting any validation). * - * @param public_key public key of the peer, NULL for unknown * @param address address to find * @return validation entry matching the given specifications, NULL * if we don't have an existing entry and no public key was given */ static struct ValidationEntry * -find_validation_entry (const struct GNUNET_CRYPTO_EddsaPublicKey *public_key, - const struct GNUNET_HELLO_Address *address) +find_validation_entry (const struct GNUNET_HELLO_Address *address) { struct ValidationEntryMatchContext vemc; struct ValidationEntry *ve; @@ -753,26 +781,25 @@ find_validation_entry (const struct GNUNET_CRYPTO_EddsaPublicKey *public_key, &validation_entry_match, &vemc); if (NULL != (ve = vemc.ve)) return ve; - if (public_key == NULL) - return NULL; ve = GNUNET_new (struct ValidationEntry); ve->in_use = GNUNET_SYSERR; /* not defined */ ve->address = GNUNET_HELLO_address_copy (address); - ve->public_key = *public_key; - ve->pid = address->peer; - ve->pong_sig_valid_until = GNUNET_TIME_absolute_get_zero_(); + ve->pong_sig_valid_until = GNUNET_TIME_UNIT_ZERO_ABS; memset (&ve->pong_sig_cache, '\0', sizeof (struct GNUNET_CRYPTO_EddsaSignature)); ve->latency = GNUNET_TIME_UNIT_FOREVER_REL; ve->challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX); ve->timeout_task = GNUNET_SCHEDULER_add_delayed (UNVALIDATED_PING_KEEPALIVE, - &timeout_hello_validation, ve); - GNUNET_CONTAINER_multipeermap_put (validation_map, &address->peer, + &timeout_hello_validation, + ve); + GNUNET_CONTAINER_multipeermap_put (validation_map, + &address->peer, ve, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); - validation_entry_changed (ve, GNUNET_TRANSPORT_VS_NEW); - ve->expecting_pong = GNUNET_NO; + publish_ve_stat_update (); + validation_entry_changed (ve, + GNUNET_TRANSPORT_VS_NEW); return ve; } @@ -784,7 +811,9 @@ find_validation_entry (const struct GNUNET_CRYPTO_EddsaPublicKey *public_key, * @param cls original HELLO message * @param address the address * @param expiration expiration time - * @return #GNUNET_OK (keep the address) + * @return #GNUNET_OK (keep the address), could return + * #GNUNET_NO (delete address, but this is ignored); + * #GNUNET_SYSERR would abort iteration (but we always iterate all) */ static int add_valid_address (void *cls, @@ -794,42 +823,43 @@ add_valid_address (void *cls, const struct GNUNET_HELLO_Message *hello = cls; struct ValidationEntry *ve; struct GNUNET_PeerIdentity pid; - struct GNUNET_ATS_Information ats; - struct GNUNET_CRYPTO_EddsaPublicKey public_key; + struct GNUNET_ATS_Properties prop; if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us) return GNUNET_OK; /* expired */ - if ((GNUNET_OK != GNUNET_HELLO_get_id (hello, &pid)) || - (GNUNET_OK != GNUNET_HELLO_get_key (hello, &public_key))) + if (GNUNET_OK != GNUNET_HELLO_get_id (hello, &pid)) { GNUNET_break (0); return GNUNET_OK; /* invalid HELLO !? */ } - if (0 == memcmp (&GST_my_identity, - &pid, - sizeof (struct GNUNET_PeerIdentity))) + if (NULL == GST_plugins_find (address->transport_name)) { - /* Peerinfo returned own identity, skip validation */ + /* might have been valid in the past, but we don't have that + plugin loaded right now */ return GNUNET_OK; } - ve = find_validation_entry (&public_key, address); - ve->valid_until = GNUNET_TIME_absolute_max (ve->valid_until, expiration); - - if (GNUNET_SCHEDULER_NO_TASK == ve->revalidation_task) + ve = find_validation_entry (address); + ve->valid_until = GNUNET_TIME_absolute_max (ve->valid_until, + expiration); + if (NULL == ve->revalidation_task) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting revalidations for valid address `%s'\n", - GST_plugins_a2s (ve->address)); + GST_plugins_a2s (ve->address)); ve->next_validation = GNUNET_TIME_absolute_get(); ve->revalidation_task = GNUNET_SCHEDULER_add_now (&revalidate_address, ve); } - validation_entry_changed (ve, GNUNET_TRANSPORT_VS_UPDATE); - - ats.type = htonl (GNUNET_ATS_NETWORK_TYPE); - ats.value = htonl (ve->network); - GNUNET_ATS_address_add (GST_ats, address, NULL, &ats, 1); - + validation_entry_changed (ve, + GNUNET_TRANSPORT_VS_UPDATE); + memset (&prop, 0, sizeof (prop)); + prop.scope = ve->network; + prop.delay = GNUNET_TIME_relative_divide (ve->latency, 2); + if (GNUNET_YES != ve->known_to_ats) + { + ve->known_to_ats = GNUNET_YES; + GST_ats_add_address (address, &prop); + } return GNUNET_OK; } @@ -837,19 +867,28 @@ add_valid_address (void *cls, /** * Function called for any HELLO known to PEERINFO. * - * @param cls unused - * @param peer id of the peer, NULL for last call + * @param cls unused (NULL) + * @param peer id of the peer, NULL for last call (during iteration, + * as we are monitoring, this should never happen) * @param hello hello message for the peer (can be NULL) * @param err_msg error message */ static void -process_peerinfo_hello (void *cls, const struct GNUNET_PeerIdentity *peer, +process_peerinfo_hello (void *cls, + const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Message *hello, const char *err_msg) { GNUNET_assert (NULL != peer); if (NULL == hello) return; + if (0 == memcmp (&GST_my_identity, + peer, + sizeof (struct GNUNET_PeerIdentity))) + { + /* Peerinfo returned own identity, skip validation */ + return; + } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Handling HELLO for peer `%s'\n", GNUNET_i2s (peer)); @@ -884,8 +923,12 @@ GST_validation_start (unsigned int max_fds) validation_delay.rel_value_us = (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value_us) / (max_fds / 2); validations_fast_start_threshold = (max_fds / 2); validations_running = 0; + GNUNET_STATISTICS_set (GST_stats, + gettext_noop ("# validations running"), + validations_running, + GNUNET_NO); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Validation uses a fast start threshold of %u connections and a delay between of %s\n ", + "Validation uses a fast start threshold of %u connections and a delay of %s\n", validations_fast_start_threshold, GNUNET_STRINGS_relative_time_to_string (validation_delay, GNUNET_YES)); @@ -902,17 +945,11 @@ GST_validation_start (unsigned int max_fds) void GST_validation_stop () { - struct CheckHelloValidatedContext *chvc; - GNUNET_CONTAINER_multipeermap_iterate (validation_map, - &cleanup_validation_entry, NULL); + &cleanup_validation_entry, + NULL); GNUNET_CONTAINER_multipeermap_destroy (validation_map); validation_map = NULL; - while (NULL != (chvc = chvc_head)) - { - GNUNET_CONTAINER_DLL_remove (chvc_head, chvc_tail, chvc); - GNUNET_free (chvc); - } GNUNET_PEERINFO_notify_cancel (pnc); } @@ -921,7 +958,6 @@ GST_validation_stop () * Send the given PONG to the given address. * * @param cls the PONG message - * @param public_key public key for the peer, never NULL * @param valid_until is ZERO if we never validated the address, * otherwise a time up to when we consider it (or was) valid * @param validation_block is FOREVER if the address is for an unsupported plugin (from PEERINFO) @@ -931,7 +967,6 @@ GST_validation_stop () */ static void multicast_pong (void *cls, - const struct GNUNET_CRYPTO_EddsaPublicKey *public_key, struct GNUNET_TIME_Absolute valid_until, struct GNUNET_TIME_Absolute validation_block, const struct GNUNET_HELLO_Address *address) @@ -942,8 +977,12 @@ multicast_pong (void *cls, papi = GST_plugins_find (address->transport_name); if (NULL == papi) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Plugin %s not supported, cannot send PONG\n", + address->transport_name); return; - + } GNUNET_assert (NULL != papi->send); GNUNET_assert (NULL != papi->get_session); session = papi->get_session(papi->cls, address); @@ -952,17 +991,16 @@ multicast_pong (void *cls, GNUNET_break (0); return; } + GST_ats_new_session (address, session); papi->send (papi->cls, session, (const char *) pong, ntohs (pong->header.size), PONG_PRIORITY, ACCEPTABLE_PING_DELAY, NULL, NULL); - GST_neighbours_notify_data_sent (&address->peer, - address, + GST_neighbours_notify_data_sent (address, session, pong->header.size); - } @@ -993,7 +1031,6 @@ GST_validation_handle_ping (const struct GNUNET_PeerIdentity *sender, size_t len_address; size_t len_plugin; ssize_t ret; - int buggy = GNUNET_NO; struct GNUNET_HELLO_Address address; if (ntohs (hdr->size) < sizeof (struct TransportPingMessage)) @@ -1065,7 +1102,10 @@ GST_validation_handle_ping (const struct GNUNET_PeerIdentity *sender, return GNUNET_SYSERR; } GNUNET_free (plugin_name); - if (GNUNET_OK != papi->check_address (papi->cls, addrend, len_address)) + if (GNUNET_OK != + papi->check_address (papi->cls, + addrend, + len_address)) { GNUNET_STATISTICS_update (GST_stats, gettext_noop @@ -1087,22 +1127,16 @@ GST_validation_handle_ping (const struct GNUNET_PeerIdentity *sender, GST_plugins_a2s (&address)); } - if (GNUNET_YES != GST_hello_test_address (&address, &sig_cache, &sig_cache_exp)) + if (GNUNET_YES != + GST_hello_test_address (&address, + &sig_cache, + &sig_cache_exp)) { - if (GNUNET_NO == buggy) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("Not confirming PING from peer `%s' with address `%s' since I cannot confirm having this address.\n"), - GNUNET_i2s (sender), - GST_plugins_a2s (&address)); - return GNUNET_SYSERR; - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - _("Received a PING message with validation bug from `%s'\n"), - GNUNET_i2s (sender)); - } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + _("Not confirming PING from peer `%s' with address `%s' since I cannot confirm having this address.\n"), + GNUNET_i2s (sender), + GST_plugins_a2s (&address)); + return GNUNET_SYSERR; } } else @@ -1163,22 +1197,23 @@ GST_validation_handle_ping (const struct GNUNET_PeerIdentity *sender, } pong->signature = *sig_cache; - GNUNET_assert (sender_address != NULL); + GNUNET_assert (NULL != sender_address); /* first see if the session we got this PING from can be used to transmit * a response reliably */ - if (papi == NULL) + if (NULL == papi) + { ret = -1; + } else { - GNUNET_assert (papi->send != NULL); - GNUNET_assert (papi->get_session != NULL); - - if (session == NULL) + GNUNET_assert (NULL != papi->send); + GNUNET_assert (NULL != papi->get_session); + if (NULL == session) { session = papi->get_session (papi->cls, sender_address); } - if (session == NULL) + if (NULL == session) { GNUNET_break (0); ret = -1; @@ -1186,12 +1221,13 @@ GST_validation_handle_ping (const struct GNUNET_PeerIdentity *sender, else { ret = papi->send (papi->cls, session, - (const char *) pong, ntohs (pong->header.size), + (const char *) pong, + ntohs (pong->header.size), PONG_PRIORITY, ACCEPTABLE_PING_DELAY, NULL, NULL); if (-1 != ret) - GST_neighbours_notify_data_sent (sender, - sender_address, session, + GST_neighbours_notify_data_sent (sender_address, + session, pong->header.size); } } @@ -1222,28 +1258,39 @@ GST_validation_handle_ping (const struct GNUNET_PeerIdentity *sender, /** - * Context for the #validate_address_iterator() function + * Validate an individual address. + * + * @param address address we should try to validate */ -struct ValidateAddressContext +void +GST_validation_handle_address (const struct GNUNET_HELLO_Address *address) { - /** - * Hash of the public key of the peer whose address is being validated. - */ - struct GNUNET_PeerIdentity pid; - - /** - * Public key of the peer whose address is being validated. - */ - struct GNUNET_CRYPTO_EddsaPublicKey public_key; + struct GNUNET_TRANSPORT_PluginFunctions *papi; + struct ValidationEntry *ve; -}; + papi = GST_plugins_find (address->transport_name); + if (NULL == papi) + { + /* This plugin is currently unvailable ... ignore */ + return; + } + ve = find_validation_entry (address); + if (NULL == ve->revalidation_task) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Validation process started for fresh address `%s' of %s\n", + GST_plugins_a2s (ve->address), + GNUNET_i2s (&ve->address->peer)); + ve->revalidation_task = GNUNET_SCHEDULER_add_now (&revalidate_address, ve); + } +} /** * Iterator callback to go over all addresses and try to validate them * (unless blocked or already validated). * - * @param cls pointer to a `struct ValidateAddressContext *` + * @param cls NULL * @param address the address * @param expiration expiration time * @return #GNUNET_OK (keep the address) @@ -1253,52 +1300,13 @@ validate_address_iterator (void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration) { - const struct ValidateAddressContext *vac = cls; - struct GNUNET_TRANSPORT_PluginFunctions * papi; - struct ValidationEntry *ve; - struct GNUNET_TIME_Relative canonical_delay; - if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Skipping expired address from HELLO\n"); return GNUNET_OK; /* expired */ } - ve = find_validation_entry (&vac->public_key, address); - - papi = GST_plugins_find (ve->address->transport_name); - if (papi == NULL) - { - /* This plugin is currently unvailable ... retry later */ - if (GNUNET_SCHEDULER_NO_TASK == ve->revalidation_task) - { - if (GNUNET_YES == ve->in_use) - canonical_delay = CONNECTED_PING_FREQUENCY; - else if (GNUNET_TIME_absolute_get_remaining (ve->valid_until).rel_value_us > 0) - canonical_delay = VALIDATED_PING_FREQUENCY; - else - canonical_delay = UNVALIDATED_PING_KEEPALIVE; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Plugin `%s' unavailable, validation process for peer `%s' delayed for %llu ms\n", - ve->address->transport_name, - GNUNET_i2s (&ve->address->peer), - (long long unsigned) canonical_delay.rel_value_us / 1000); - - ve->revalidation_task = GNUNET_SCHEDULER_add_delayed (canonical_delay, - &revalidate_address, ve); - } - return GNUNET_OK; - } - - - if (GNUNET_SCHEDULER_NO_TASK == ve->revalidation_task) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Validation process started for fresh address `%s'\n", - GST_plugins_a2s (ve->address)); - ve->revalidation_task = GNUNET_SCHEDULER_add_now (&revalidate_address, ve); - } + GST_validation_handle_address (address); return GNUNET_OK; } @@ -1322,7 +1330,10 @@ add_valid_peer_address (void *cls, if (GNUNET_YES == ve->copied) return GNUNET_SYSERR; /* Done */ ve->copied = GNUNET_YES; - return GNUNET_HELLO_add_address (ve->address, ve->valid_until, buf, max); + return GNUNET_HELLO_add_address (ve->address, + ve->valid_until, + buf, + max); } @@ -1374,12 +1385,22 @@ GST_validation_handle_pong (const struct GNUNET_PeerIdentity *sender, addr++; slen = strlen (tname) + 1; addrlen = size - slen; + + if (NULL == GST_plugins_find (tname)) + { + /* we got the PONG, but the transport plugin specified in it + is not supported by this peer, so this cannot be a good + PONG for us. */ + GNUNET_break_op (0); + return GNUNET_OK; + } + address.peer = *sender; address.address = addr; address.address_length = addrlen; address.transport_name = tname; address.local_info = GNUNET_HELLO_ADDRESS_INFO_NONE; - ve = find_validation_entry (NULL, &address); + ve = find_validation_entry (&address); if ((NULL == ve) || (GNUNET_NO == ve->expecting_pong)) { GNUNET_STATISTICS_update (GST_stats, @@ -1389,13 +1410,16 @@ GST_validation_handle_pong (const struct GNUNET_PeerIdentity *sender, return GNUNET_OK; } /* now check that PONG is well-formed */ - if (0 != memcmp (&ve->pid, sender, sizeof (struct GNUNET_PeerIdentity))) + if (0 != memcmp (&ve->address->peer, + sender, + sizeof (struct GNUNET_PeerIdentity))) { GNUNET_break_op (0); return GNUNET_SYSERR; } - if (GNUNET_TIME_absolute_get_remaining - (GNUNET_TIME_absolute_ntoh (pong->expiration)).rel_value_us == 0) + if (0 == + GNUNET_TIME_absolute_get_remaining + (GNUNET_TIME_absolute_ntoh (pong->expiration)).rel_value_us) { GNUNET_STATISTICS_update (GST_stats, gettext_noop @@ -1410,7 +1434,9 @@ GST_validation_handle_pong (const struct GNUNET_PeerIdentity *sender, { /* We have a cached and valid signature for this peer, * try to compare instead of verify */ - if (0 == memcmp (&ve->pong_sig_cache, &pong->signature, sizeof (struct GNUNET_CRYPTO_EddsaSignature))) + if (0 == memcmp (&ve->pong_sig_cache, + &pong->signature, + sizeof (struct GNUNET_CRYPTO_EddsaSignature))) { /* signatures are identical, we can skip verification */ sig_res = GNUNET_OK; @@ -1427,8 +1453,9 @@ GST_validation_handle_pong (const struct GNUNET_PeerIdentity *sender, { /* Do expensive verification */ sig_res = GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN, - &pong->purpose, &pong->signature, - &ve->public_key); + &pong->purpose, + &pong->signature, + &ve->address->peer.public_key); if (sig_res == GNUNET_SYSERR) { GNUNET_break_op (0); @@ -1450,24 +1477,40 @@ GST_validation_handle_pong (const struct GNUNET_PeerIdentity *sender, GNUNET_i2s (sender), tname, GST_plugins_a2s (ve->address)); + GNUNET_STATISTICS_update (GST_stats, + gettext_noop ("# validations succeeded"), + 1, + GNUNET_NO); /* validity achieved, remember it! */ ve->expecting_pong = GNUNET_NO; ve->valid_until = GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION); ve->pong_sig_cache = pong->signature; - ve->pong_sig_valid_until = GNUNET_TIME_absolute_ntoh (pong->expiration); + ve->pong_sig_valid_until = GNUNET_TIME_absolute_ntoh (pong->expiration); ve->latency = GNUNET_TIME_absolute_get_duration (ve->send_time); { - struct GNUNET_ATS_Information ats[2]; + if (GNUNET_YES == ve->known_to_ats) + { + GST_ats_update_delay (ve->address, + GNUNET_TIME_relative_divide (ve->latency, 2)); + } + else + { + struct GNUNET_ATS_Properties prop; - ats[0].type = htonl (GNUNET_ATS_QUALITY_NET_DELAY); - ats[0].value = htonl ((uint32_t) ve->latency.rel_value_us); - ats[1].type = htonl (GNUNET_ATS_NETWORK_TYPE); - ats[1].value = htonl ((uint32_t) ve->network); - GNUNET_ATS_address_add (GST_ats, ve->address, NULL, ats, 2); + memset (&prop, 0, sizeof (prop)); + prop.scope = ve->network; + prop.delay = GNUNET_TIME_relative_divide (ve->latency, 2); + ve->known_to_ats = GNUNET_YES; + GST_ats_add_address (ve->address, &prop); + } } if (validations_running > 0) { - validations_running --; + validations_running--; + GNUNET_STATISTICS_set (GST_stats, + gettext_noop ("# validations running"), + validations_running, + GNUNET_NO); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Validation finished, %u validation processes running\n", validations_running); @@ -1478,14 +1521,19 @@ GST_validation_handle_pong (const struct GNUNET_PeerIdentity *sender, } /* Notify about new validity */ - validation_entry_changed (ve, GNUNET_TRANSPORT_VS_UPDATE); + validation_entry_changed (ve, + GNUNET_TRANSPORT_VS_UPDATE); /* build HELLO to store in PEERINFO */ ve->copied = GNUNET_NO; - hello = GNUNET_HELLO_create (&ve->public_key, - &add_valid_peer_address, ve, + hello = GNUNET_HELLO_create (&ve->address->peer.public_key, + &add_valid_peer_address, + ve, GNUNET_NO); - GNUNET_PEERINFO_add_peer (GST_peerinfo, hello, NULL, NULL); + GNUNET_PEERINFO_add_peer (GST_peerinfo, + hello, + NULL, + NULL); GNUNET_free (hello); return GNUNET_OK; } @@ -1503,41 +1551,35 @@ GST_validation_handle_hello (const struct GNUNET_MessageHeader *hello) { const struct GNUNET_HELLO_Message *hm = (const struct GNUNET_HELLO_Message *) hello; - struct ValidateAddressContext vac; - struct GNUNET_HELLO_Message *h; + struct GNUNET_PeerIdentity pid; int friend; friend = GNUNET_HELLO_is_friend_only (hm); if ( ( (GNUNET_YES != friend) && (GNUNET_NO != friend) ) || - (GNUNET_OK != GNUNET_HELLO_get_id (hm, &vac.pid)) || - (GNUNET_OK != GNUNET_HELLO_get_key (hm, &vac.public_key))) + (GNUNET_OK != GNUNET_HELLO_get_id (hm, &pid)) ) { /* malformed HELLO */ GNUNET_break_op (0); return GNUNET_SYSERR; } if (0 == - memcmp (&GST_my_identity, &vac.pid, sizeof (struct GNUNET_PeerIdentity))) + memcmp (&GST_my_identity, + &pid, + sizeof (struct GNUNET_PeerIdentity))) + { + /* got our own HELLO, how boring */ return GNUNET_OK; - /* Add peer identity without addresses to peerinfo service */ - h = GNUNET_HELLO_create (&vac.public_key, NULL, NULL, friend); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("Validation received new %s message for peer `%s' with size %u\n"), - "HELLO", - GNUNET_i2s (&vac.pid), - ntohs (hello->size)); - GNUNET_PEERINFO_add_peer (GST_peerinfo, h, NULL, NULL); - + } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - _("Adding `%s' without addresses for peer `%s'\n"), "HELLO", - GNUNET_i2s (&vac.pid)); - - GNUNET_free (h); + "Validation received HELLO message for peer `%s' with size %u, checking for new addresses\n", + GNUNET_i2s (&pid), + ntohs (hello->size)); GNUNET_assert (NULL == - GNUNET_HELLO_iterate_addresses (hm, GNUNET_NO, + GNUNET_HELLO_iterate_addresses (hm, + GNUNET_NO, &validate_address_iterator, - &vac)); + NULL)); return GNUNET_OK; } @@ -1576,7 +1618,9 @@ iterate_addresses (void *cls, struct IteratorContext *ic = cls; struct ValidationEntry *ve = value; - ic->cb (ic->cb_cls, &ve->public_key, ve->valid_until, ve->revalidation_block, + ic->cb (ic->cb_cls, + ve->valid_until, + ve->revalidation_block, ve->address); return GNUNET_OK; } @@ -1592,7 +1636,8 @@ iterate_addresses (void *cls, */ void GST_validation_get_addresses (const struct GNUNET_PeerIdentity *target, - GST_ValidationAddressCallback cb, void *cb_cls) + GST_ValidationAddressCallback cb, + void *cb_cls) { struct IteratorContext ic; @@ -1609,83 +1654,45 @@ GST_validation_get_addresses (const struct GNUNET_PeerIdentity *target, * Based on this, the validation module will measure latency for the * address more or less often. * - * @param address the address - * @param session the session + * @param address the address that we are now using (or not) * @param in_use #GNUNET_YES if we are now using the address for a connection, * #GNUNET_NO if we are no longer using the address for a connection */ void GST_validation_set_address_use (const struct GNUNET_HELLO_Address *address, - struct Session *session, int in_use) { struct ValidationEntry *ve; - if (NULL != address) - ve = find_validation_entry (NULL, address); - else - ve = NULL; /* FIXME: lookup based on session... */ - if (NULL == ve) + if (GNUNET_HELLO_address_check_option (address, + GNUNET_HELLO_ADDRESS_INFO_INBOUND)) + return; /* ignore inbound for validation */ + if (NULL == GST_plugins_find (address->transport_name)) { - /* this can happen for inbound connections (sender_address_len == 0); */ + /* How can we use an address for which we don't have the plugin? */ + GNUNET_break (0); return; } - if (ve->in_use == in_use) + ve = find_validation_entry (address); + if (NULL == ve) { - - if (GNUNET_YES == in_use) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Error setting address in use for peer `%s' `%s' to USED\n", - GNUNET_i2s (&address->peer), GST_plugins_a2s (address)); - } - if (GNUNET_NO == in_use) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Error setting address in use for peer `%s' `%s' to NOT_USED\n", - GNUNET_i2s (&address->peer), GST_plugins_a2s (address)); - } + GNUNET_break (0); + return; } - - GNUNET_break (ve->in_use != in_use); /* should be different... */ + if (in_use == ve->in_use) + return; ve->in_use = in_use; - if (in_use == GNUNET_YES) + if (GNUNET_YES == in_use) { /* from now on, higher frequeny, so reschedule now */ - GNUNET_SCHEDULER_cancel (ve->revalidation_task); - ve->revalidation_task = GNUNET_SCHEDULER_add_now (&revalidate_address, ve); + if (NULL != ve->revalidation_task) + GNUNET_SCHEDULER_cancel (ve->revalidation_task); + ve->revalidation_task = GNUNET_SCHEDULER_add_now (&revalidate_address, + ve); } } -/** - * Query validation about the latest observed latency on a given - * address. - * - * @param sender peer - * @param address the address - * @param session session - * @return observed latency of the address, FOREVER if the address was - * never successfully validated - */ -struct GNUNET_TIME_Relative -GST_validation_get_address_latency (const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_HELLO_Address *address, - struct Session *session) -{ - struct ValidationEntry *ve; - - if (NULL == address) - { - GNUNET_break (0); // FIXME: support having latency only with session... - return GNUNET_TIME_UNIT_FOREVER_REL; - } - ve = find_validation_entry (NULL, address); - if (NULL == ve) - return GNUNET_TIME_UNIT_FOREVER_REL; - return ve->latency; -} - /** * Closure for the validation_entries_iterate function. */ @@ -1703,27 +1710,43 @@ struct ValidationIteratorContext }; +/** + * Function called on each entry in the validation map. + * Passes the information from the validation entry to + * the callback given in the closure. + * + * @param cls the `struct ValidationIteratorContext` + * @param key peer this is about + * @param value the `struct ValidationEntry` + * @return #GNUNET_OK (continue to iterate) + */ static int validation_entries_iterate (void *cls, - const struct GNUNET_PeerIdentity *key, - void *value) + const struct GNUNET_PeerIdentity *key, + void *value) { struct ValidationIteratorContext *ic = cls; struct ValidationEntry *ve = value; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Notifying about validation entry for peer `%s' address `%s' \n", - GNUNET_i2s (&ve->pid), GST_plugins_a2s (ve->address)); - ic->cb (ic->cb_cls, &ve->pid, ve->address, ve->send_time, - ve->valid_until, ve->next_validation, ve->state); - + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Notifying about validation entry for peer `%s' address `%s' \n", + GNUNET_i2s (&ve->address->peer), + GST_plugins_a2s (ve->address)); + ic->cb (ic->cb_cls, + ve->address, + ve->send_time, + ve->valid_until, + ve->next_validation, + ve->state); return GNUNET_OK; } + /** * Iterate over all iteration entries * * @param cb function to call - * @param cb_cls closure for cb + * @param cb_cls closure for @a cb */ void GST_validation_iterate (GST_ValidationChangedCallback cb,