aboutsummaryrefslogtreecommitdiff
path: root/src/dns/dnsstub.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2018-03-30 20:55:42 +0200
committerChristian Grothoff <christian@grothoff.org>2018-03-30 20:55:42 +0200
commit466b556fda9d5b946e0099bfbe53099c52bcb433 (patch)
tree3fd3de33d608c26ae6526136a134f76e3ecc501f /src/dns/dnsstub.c
parentd9c9f4dd2f61620d1848c8c32a36341ec1f1e41e (diff)
retry DNS queries, as DNS is UDP-based and hence unreliable
Diffstat (limited to 'src/dns/dnsstub.c')
-rw-r--r--src/dns/dnsstub.c115
1 files changed, 88 insertions, 27 deletions
diff --git a/src/dns/dnsstub.c b/src/dns/dnsstub.c
index 68cd552750..364b6fe284 100644
--- a/src/dns/dnsstub.c
+++ b/src/dns/dnsstub.c
@@ -33,6 +33,11 @@
#define REQUEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
/**
+ * Timeout for retrying DNS queries.
+ */
+#define DNS_RETRANSMIT_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 250)
+
+/**
* How many DNS sockets do we open at most at the same time?
* (technical socket maximum is this number x2 for IPv4+IPv6)
*/
@@ -68,7 +73,12 @@ struct GNUNET_DNSSTUB_RequestSocket
/**
* Task for reading from dnsout4 and dnsout6.
*/
- struct GNUNET_SCHEDULER_Task * read_task;
+ struct GNUNET_SCHEDULER_Task *read_task;
+
+ /**
+ * Task for retrying transmission of the query.
+ */
+ struct GNUNET_SCHEDULER_Task *retry_task;
/**
* When should this request time out?
@@ -85,6 +95,16 @@ struct GNUNET_DNSSTUB_RequestSocket
*/
socklen_t addrlen;
+ /**
+ * Query we sent to @e addr.
+ */
+ void *request;
+
+ /**
+ * Number of bytes in @a request.
+ */
+ size_t request_len;
+
};
@@ -107,7 +127,6 @@ struct GNUNET_DNSSTUB_Context
};
-
/**
* We're done with a `struct GNUNET_DNSSTUB_RequestSocket`, close it for now.
*
@@ -131,6 +150,16 @@ cleanup_rs (struct GNUNET_DNSSTUB_RequestSocket *rs)
GNUNET_SCHEDULER_cancel (rs->read_task);
rs->read_task = NULL;
}
+ if (NULL != rs->retry_task)
+ {
+ GNUNET_SCHEDULER_cancel (rs->retry_task);
+ rs->retry_task = NULL;
+ }
+ if (NULL != rs->request)
+ {
+ GNUNET_free (rs->request);
+ rs->request = NULL;
+ }
}
@@ -227,6 +256,16 @@ get_request_socket (struct GNUNET_DNSSTUB_Context *ctx,
GNUNET_SCHEDULER_cancel (rs->read_task);
rs->read_task = NULL;
}
+ if (NULL != rs->retry_task)
+ {
+ GNUNET_SCHEDULER_cancel (rs->retry_task);
+ rs->retry_task = NULL;
+ }
+ if (NULL != rs->request)
+ {
+ GNUNET_free (rs->request);
+ rs->request = NULL;
+ }
if ( (NULL == rs->dnsout4) &&
(NULL == rs->dnsout6) )
return NULL;
@@ -239,13 +278,50 @@ get_request_socket (struct GNUNET_DNSSTUB_Context *ctx,
REQUEST_TIMEOUT,
rset,
NULL,
- &read_response, rs);
+ &read_response,
+ rs);
GNUNET_NETWORK_fdset_destroy (rset);
return rs;
}
/**
+ * Task to (re)transmit the DNS query, possibly repeatedly until
+ * we succeed.
+ *
+ * @param cls our `struct GNUNET_DNSSTUB_RequestSocket *`
+ */
+static void
+transmit_query (void *cls)
+{
+ struct GNUNET_DNSSTUB_RequestSocket *rs = cls;
+ struct GNUNET_NETWORK_Handle *ret;
+
+ rs->retry_task = NULL;
+ ret = (NULL != rs->dnsout4) ? rs->dnsout4 : rs->dnsout6;
+ GNUNET_assert (NULL != ret);
+ if (GNUNET_SYSERR ==
+ GNUNET_NETWORK_socket_sendto (ret,
+ rs->request,
+ rs->request_len,
+ (struct sockaddr *) &rs->addr,
+ rs->addrlen))
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("Failed to send DNS request to %s\n"),
+ GNUNET_a2s ((struct sockaddr *) &rs->addr,
+ rs->addrlen));
+ else
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ _("Sent DNS request to %s\n"),
+ GNUNET_a2s ((struct sockaddr *) &rs->addr,
+ rs->addrlen));
+ rs->retry_task = GNUNET_SCHEDULER_add_delayed (DNS_RETRANSMIT_DELAY,
+ &transmit_query,
+ rs);
+}
+
+
+/**
* Perform DNS resolution.
*
* @param ctx stub resolver to use
@@ -267,36 +343,21 @@ GNUNET_DNSSTUB_resolve (struct GNUNET_DNSSTUB_Context *ctx,
void *rc_cls)
{
struct GNUNET_DNSSTUB_RequestSocket *rs;
- struct GNUNET_NETWORK_Handle *ret;
- int af;
- af = sa->sa_family;
- if (NULL == (rs = get_request_socket (ctx, af)))
+ if (NULL == (rs = get_request_socket (ctx,
+ sa->sa_family)))
return NULL;
- if (NULL != rs->dnsout4)
- ret = rs->dnsout4;
- else
- ret = rs->dnsout6;
- GNUNET_assert (NULL != ret);
GNUNET_memcpy (&rs->addr,
- sa,
- sa_len);
+ sa,
+ sa_len);
rs->addrlen = sa_len;
rs->rc = rc;
rs->rc_cls = rc_cls;
- if (GNUNET_SYSERR ==
- GNUNET_NETWORK_socket_sendto (ret,
- request,
- request_len,
- sa,
- sa_len))
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("Failed to send DNS request to %s\n"),
- GNUNET_a2s (sa, sa_len));
- else
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- _("Sent DNS request to %s\n"),
- GNUNET_a2s (sa, sa_len));
+ rs->request = GNUNET_memdup (request,
+ request_len);
+ rs->request_len = request_len;
+ rs->retry_task = GNUNET_SCHEDULER_add_now (&transmit_query,
+ rs);
return rs;
}