From 0fa4ab3fc8efce8bbf87c522ce9ce1344d98d9fb Mon Sep 17 00:00:00 2001 From: Ludvig Strigeus Date: Fri, 19 Oct 2018 13:40:39 +0200 Subject: [PATCH] Allow dns request to be reattempted right away --- TunSafe.vcxproj | 1 + TunSafe.vcxproj.filters | 3 +++ tunsafe_dnsresolve.h | 6 +++++- tunsafe_ipaddr.cpp | 42 ++++++++++++++++++++++++++++++++++------- 4 files changed, 44 insertions(+), 8 deletions(-) diff --git a/TunSafe.vcxproj b/TunSafe.vcxproj index 94651a4..ea793d3 100644 --- a/TunSafe.vcxproj +++ b/TunSafe.vcxproj @@ -195,6 +195,7 @@ + diff --git a/TunSafe.vcxproj.filters b/TunSafe.vcxproj.filters index a035bde..77805db 100644 --- a/TunSafe.vcxproj.filters +++ b/TunSafe.vcxproj.filters @@ -123,6 +123,9 @@ Source Files + + Source Files + diff --git a/tunsafe_dnsresolve.h b/tunsafe_dnsresolve.h index f3a1ff4..5733057 100644 --- a/tunsafe_dnsresolve.h +++ b/tunsafe_dnsresolve.h @@ -8,12 +8,14 @@ class DnsBlocker; class DnsResolverCanceller { public: - DnsResolverCanceller() : cancel_(false) {} + DnsResolverCanceller() : cancel_(false), cancel_sleep_once_(false) {} void Cancel(); + void CancelSleepOnce(); void Reset() { cancel_ = false; } bool is_cancelled() { return cancel_; } public: bool cancel_; + bool cancel_sleep_once_; ConditionVariable condvar_; }; @@ -25,6 +27,7 @@ public: bool Resolve(const char *hostname, IpAddr *result); void ClearCache(); + void RetryNow(); void Cancel() { token_.Cancel(); } void ResetCancel() { token_.Reset(); } private: @@ -36,6 +39,7 @@ private: std::vector cache_; DnsBlocker *dns_blocker_; DnsResolverCanceller token_; + int retry_attempt_; }; #endif // TUNSAFE_DNSRESOLVE_H_ \ No newline at end of file diff --git a/tunsafe_ipaddr.cpp b/tunsafe_ipaddr.cpp index aed2abf..94b0809 100644 --- a/tunsafe_ipaddr.cpp +++ b/tunsafe_ipaddr.cpp @@ -140,6 +140,15 @@ void DnsResolverCanceller::Cancel() { g_dns_mutex.Release(); } +void DnsResolverCanceller::CancelSleepOnce() { + g_dns_mutex.Acquire(); + cancel_sleep_once_ = true; + condvar_.Wake(); + g_dns_mutex.Release(); +} + + + bool DnsResolverThread::Resolve(const char *hostname, IpAddr *result, DnsResolverCanceller *token) { if (token->cancel_) return false; @@ -188,15 +197,23 @@ void DnsResolverThread::ThreadMain() { struct addrinfo hints = {0}; hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; + // AI_V4MAPPED doesn't work on Android?! +#if defined(OS_IOS) hints.ai_flags = AI_DEFAULT; +#else + hints.ai_flags = AI_ADDRCONFIG ; +#endif ai = NULL; - if (getaddrinfo(e->hostname, NULL, &hints, &ai) != 0) + int r = getaddrinfo(e->hostname, NULL, &hints, &ai); + if (r != 0) ai = NULL; +// RINFO("r=%d errno=%d, %s", r, errno, gai_strerror(r)); // he = gethostbyname(e->hostname); g_dns_mutex.Acquire(); if (e->state == Entry::CANCELLED) { delete e; } else { +// RINFO("ai=%p, family=%d", ai, ai ? ai->ai_family : -1); if (ai) { e->result->sin.sin_family = ai->ai_family; e->result->sin.sin_port = 0; @@ -228,6 +245,11 @@ static bool InterruptibleSleep(int delay, DnsResolverCanceller *token) { g_dns_mutex.Acquire(); uint32 time_at_start = (uint32)OsGetMilliseconds(); while (delay > 0 && !token->cancel_) { + if (token->cancel_sleep_once_) { + token->cancel_sleep_once_ = false; + delay = 0; + break; + } token->condvar_.WaitTimed(&g_dns_mutex, delay); uint32 now = (uint32)OsGetMilliseconds(); delay -= (now - time_at_start); @@ -249,10 +271,11 @@ void DnsResolver::ClearCache() { } bool DnsResolver::Resolve(const char *hostname, IpAddr *result) { - int attempt = 0; - static const uint8 retry_delays[] = {1, 2, 3, 5, 10}; + static const uint8 retry_delays[] = {1, 2, 3, 5, 10, 20, 40, 60, 120, 180, 255}; char buf[kSizeOfAddress]; + retry_attempt_ = 0; + memset(result, 0, sizeof(IpAddr)); // First check cache @@ -283,15 +306,20 @@ bool DnsResolver::Resolve(const char *hostname, IpAddr *result) { if (token_.is_cancelled()) return false; - RINFO("Unable to resolve %s. Trying again in %d second(s)", hostname, retry_delays[attempt]); - if (!InterruptibleSleep(retry_delays[attempt] * 1000, &token_)) + RINFO("Unable to resolve %s. Trying again in %d second(s)", hostname, retry_delays[retry_attempt_]); + if (!InterruptibleSleep(retry_delays[retry_attempt_] * 1000, &token_)) return false; - if (attempt != ARRAY_SIZE(retry_delays) - 1) - attempt++; + if (retry_attempt_ != ARRAY_SIZE(retry_delays) - 1) + retry_attempt_++; } } +void DnsResolver::RetryNow() { + retry_attempt_ = 0; + token_.CancelSleepOnce(); +} + // Parse an IPV4 address into sin, doing NAT64 translation if applicable (on IOS) static bool ParseIpv4WithNAT64Translation(const char *s, IpAddr *sin, int flags) { // First verify it's actually a valid ipv4 address to prevent getaddrinfo from doing a slow resolve