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:
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);
}
}