gnunet

Main GNUnet Logic
Log | Files | Refs | Submodules | README | LICENSE

commit ce9a07ad8e6d0e58bda9ca4d3e8ff357997d517c
parent a0fd1312543aea6391b5a391153ce3672f1bbd6a
Author: Martin Schanzenbach <schanzen@gnunet.org>
Date:   Thu,  6 Aug 2026 18:17:40 +0200

gns: time out and retry a DHT lookup

Diffstat:
Msrc/service/gns/gnunet-service-gns_resolver.c | 80++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 79 insertions(+), 1 deletion(-)

diff --git a/src/service/gns/gnunet-service-gns_resolver.c b/src/service/gns/gnunet-service-gns_resolver.c @@ -58,6 +58,12 @@ GNUNET_TIME_UNIT_SECONDS, 60) /** + * How often do we restart a DHT lookup that stayed unanswered for + * #DHT_LOOKUP_TIMEOUT before we give up on the name? + */ +#define DHT_LOOKUP_RETRIES 2 + +/** * Default timeout for DNS lookups. */ #define DNS_LOOKUP_TIMEOUT GNUNET_TIME_relative_multiply ( \ @@ -309,6 +315,12 @@ struct GNS_ResolverHandle struct GNUNET_CONTAINER_HeapNode *dht_heap_node; /** + * Key of the DHT GET in @e get_handle, so that we can re-issue it + * when it times out. + */ + struct GNUNET_HashCode dht_query; + + /** * DLL to store the authority chain */ struct AuthorityChain *ac_head; @@ -390,6 +402,12 @@ struct GNS_ResolverHandle unsigned int loop_threshold; /** + * How many times did we already restart the DHT GET in @e get_handle + * because it did not answer within #DHT_LOOKUP_TIMEOUT? + */ + unsigned int dht_retries; + + /** * 16 bit random ID we used in the @e dns_request. */ uint16_t original_dns_id; @@ -2546,6 +2564,13 @@ handle_dht_response (void *cls, rh->get_handle = NULL; GNUNET_CONTAINER_heap_remove_node (rh->dht_heap_node); rh->dht_heap_node = NULL; + /* must be cleared before handle_gns_resolution_result() below gets + to schedule the next step */ + if (NULL != rh->task_id) + { + GNUNET_SCHEDULER_cancel (rh->task_id); + rh->task_id = NULL; + } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Handling response from the DHT\n"); if (size < sizeof(struct GNUNET_GNSRECORD_Block)) @@ -2612,11 +2637,55 @@ handle_dht_response (void *cls, */ static void start_dht_request (struct GNS_ResolverHandle *rh, + const struct GNUNET_HashCode *query); + + +/** + * The DHT did not answer within #DHT_LOOKUP_TIMEOUT. Restart the GET + * (which also restarts the DHT service's own retry back-off for it), + * or fail the resolution once we ran out of attempts. + * + * @param cls the `struct GNS_ResolverHandle` + */ +static void +dht_lookup_timeout (void *cls) +{ + struct GNS_ResolverHandle *rh = cls; + struct GNUNET_HashCode query = rh->dht_query; + + rh->task_id = NULL; + GNUNET_DHT_get_stop (rh->get_handle); + rh->get_handle = NULL; + GNUNET_CONTAINER_heap_remove_node (rh->dht_heap_node); + rh->dht_heap_node = NULL; + if (rh->dht_retries >= DHT_LOOKUP_RETRIES) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _ ("DHT lookup for `%s' timed out\n"), + rh->name); + fail_resolution (rh); + return; + } + rh->dht_retries++; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "DHT lookup for `%s' under key %s timed out, retrying (%u/%u)\n", + rh->name, + GNUNET_h2s (&query), + rh->dht_retries, + (unsigned int) DHT_LOOKUP_RETRIES); + start_dht_request (rh, + &query); +} + + +static void +start_dht_request (struct GNS_ResolverHandle *rh, const struct GNUNET_HashCode *query) { struct GNS_ResolverHandle *rx; GNUNET_assert (NULL == rh->get_handle); + rh->dht_query = *query; rh->get_handle = GNUNET_DHT_get_start (dht_handle, GNUNET_BLOCK_TYPE_GNS_NAMERECORD, query, @@ -2628,13 +2697,22 @@ start_dht_request (struct GNS_ResolverHandle *rh, rh, GNUNET_TIME_absolute_get (). abs_value_us); + GNUNET_assert (NULL == rh->task_id); + rh->task_id = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT, + &dht_lookup_timeout, + rh); if (GNUNET_CONTAINER_heap_get_size (dht_lookup_heap) > max_allowed_background_queries) { /* fail longest-standing DHT request */ rx = GNUNET_CONTAINER_heap_remove_root (dht_lookup_heap); - rx->dht_heap_node = NULL; GNUNET_assert (NULL != rx); + rx->dht_heap_node = NULL; + if (NULL != rx->task_id) + { + GNUNET_SCHEDULER_cancel (rx->task_id); + rx->task_id = NULL; + } fail_resolution (rx); } }