Allow dns request to be reattempted right away
This commit is contained in:
parent
3c1647f72f
commit
0fa4ab3fc8
|
@ -195,6 +195,7 @@
|
||||||
<ClInclude Include="crypto\blake2s\blake2s.h" />
|
<ClInclude Include="crypto\blake2s\blake2s.h" />
|
||||||
<ClInclude Include="crypto\chacha20poly1305.h" />
|
<ClInclude Include="crypto\chacha20poly1305.h" />
|
||||||
<ClInclude Include="crypto\siphash\siphash.h" />
|
<ClInclude Include="crypto\siphash\siphash.h" />
|
||||||
|
<ClInclude Include="tunsafe_dnsresolve.h" />
|
||||||
<ClInclude Include="tunsafe_endian.h" />
|
<ClInclude Include="tunsafe_endian.h" />
|
||||||
<ClInclude Include="ipzip2\ipzip2.h" />
|
<ClInclude Include="ipzip2\ipzip2.h" />
|
||||||
<ClInclude Include="netapi.h" />
|
<ClInclude Include="netapi.h" />
|
||||||
|
|
|
@ -123,6 +123,9 @@
|
||||||
<ClInclude Include="tunsafe_ipaddr.h">
|
<ClInclude Include="tunsafe_ipaddr.h">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="tunsafe_dnsresolve.h">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="stdafx.cpp">
|
<ClCompile Include="stdafx.cpp">
|
||||||
|
|
|
@ -8,12 +8,14 @@ class DnsBlocker;
|
||||||
|
|
||||||
class DnsResolverCanceller {
|
class DnsResolverCanceller {
|
||||||
public:
|
public:
|
||||||
DnsResolverCanceller() : cancel_(false) {}
|
DnsResolverCanceller() : cancel_(false), cancel_sleep_once_(false) {}
|
||||||
void Cancel();
|
void Cancel();
|
||||||
|
void CancelSleepOnce();
|
||||||
void Reset() { cancel_ = false; }
|
void Reset() { cancel_ = false; }
|
||||||
bool is_cancelled() { return cancel_; }
|
bool is_cancelled() { return cancel_; }
|
||||||
public:
|
public:
|
||||||
bool cancel_;
|
bool cancel_;
|
||||||
|
bool cancel_sleep_once_;
|
||||||
ConditionVariable condvar_;
|
ConditionVariable condvar_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -25,6 +27,7 @@ public:
|
||||||
bool Resolve(const char *hostname, IpAddr *result);
|
bool Resolve(const char *hostname, IpAddr *result);
|
||||||
void ClearCache();
|
void ClearCache();
|
||||||
|
|
||||||
|
void RetryNow();
|
||||||
void Cancel() { token_.Cancel(); }
|
void Cancel() { token_.Cancel(); }
|
||||||
void ResetCancel() { token_.Reset(); }
|
void ResetCancel() { token_.Reset(); }
|
||||||
private:
|
private:
|
||||||
|
@ -36,6 +39,7 @@ private:
|
||||||
std::vector<Entry> cache_;
|
std::vector<Entry> cache_;
|
||||||
DnsBlocker *dns_blocker_;
|
DnsBlocker *dns_blocker_;
|
||||||
DnsResolverCanceller token_;
|
DnsResolverCanceller token_;
|
||||||
|
int retry_attempt_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TUNSAFE_DNSRESOLVE_H_
|
#endif // TUNSAFE_DNSRESOLVE_H_
|
|
@ -140,6 +140,15 @@ void DnsResolverCanceller::Cancel() {
|
||||||
g_dns_mutex.Release();
|
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) {
|
bool DnsResolverThread::Resolve(const char *hostname, IpAddr *result, DnsResolverCanceller *token) {
|
||||||
if (token->cancel_)
|
if (token->cancel_)
|
||||||
return false;
|
return false;
|
||||||
|
@ -188,15 +197,23 @@ void DnsResolverThread::ThreadMain() {
|
||||||
struct addrinfo hints = {0};
|
struct addrinfo hints = {0};
|
||||||
hints.ai_family = PF_UNSPEC;
|
hints.ai_family = PF_UNSPEC;
|
||||||
hints.ai_socktype = SOCK_DGRAM;
|
hints.ai_socktype = SOCK_DGRAM;
|
||||||
|
// AI_V4MAPPED doesn't work on Android?!
|
||||||
|
#if defined(OS_IOS)
|
||||||
hints.ai_flags = AI_DEFAULT;
|
hints.ai_flags = AI_DEFAULT;
|
||||||
|
#else
|
||||||
|
hints.ai_flags = AI_ADDRCONFIG ;
|
||||||
|
#endif
|
||||||
ai = NULL;
|
ai = NULL;
|
||||||
if (getaddrinfo(e->hostname, NULL, &hints, &ai) != 0)
|
int r = getaddrinfo(e->hostname, NULL, &hints, &ai);
|
||||||
|
if (r != 0)
|
||||||
ai = NULL;
|
ai = NULL;
|
||||||
|
// RINFO("r=%d errno=%d, %s", r, errno, gai_strerror(r));
|
||||||
// he = gethostbyname(e->hostname);
|
// he = gethostbyname(e->hostname);
|
||||||
g_dns_mutex.Acquire();
|
g_dns_mutex.Acquire();
|
||||||
if (e->state == Entry::CANCELLED) {
|
if (e->state == Entry::CANCELLED) {
|
||||||
delete e;
|
delete e;
|
||||||
} else {
|
} else {
|
||||||
|
// RINFO("ai=%p, family=%d", ai, ai ? ai->ai_family : -1);
|
||||||
if (ai) {
|
if (ai) {
|
||||||
e->result->sin.sin_family = ai->ai_family;
|
e->result->sin.sin_family = ai->ai_family;
|
||||||
e->result->sin.sin_port = 0;
|
e->result->sin.sin_port = 0;
|
||||||
|
@ -228,6 +245,11 @@ static bool InterruptibleSleep(int delay, DnsResolverCanceller *token) {
|
||||||
g_dns_mutex.Acquire();
|
g_dns_mutex.Acquire();
|
||||||
uint32 time_at_start = (uint32)OsGetMilliseconds();
|
uint32 time_at_start = (uint32)OsGetMilliseconds();
|
||||||
while (delay > 0 && !token->cancel_) {
|
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);
|
token->condvar_.WaitTimed(&g_dns_mutex, delay);
|
||||||
uint32 now = (uint32)OsGetMilliseconds();
|
uint32 now = (uint32)OsGetMilliseconds();
|
||||||
delay -= (now - time_at_start);
|
delay -= (now - time_at_start);
|
||||||
|
@ -249,10 +271,11 @@ void DnsResolver::ClearCache() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DnsResolver::Resolve(const char *hostname, IpAddr *result) {
|
bool DnsResolver::Resolve(const char *hostname, IpAddr *result) {
|
||||||
int attempt = 0;
|
static const uint8 retry_delays[] = {1, 2, 3, 5, 10, 20, 40, 60, 120, 180, 255};
|
||||||
static const uint8 retry_delays[] = {1, 2, 3, 5, 10};
|
|
||||||
char buf[kSizeOfAddress];
|
char buf[kSizeOfAddress];
|
||||||
|
|
||||||
|
retry_attempt_ = 0;
|
||||||
|
|
||||||
memset(result, 0, sizeof(IpAddr));
|
memset(result, 0, sizeof(IpAddr));
|
||||||
|
|
||||||
// First check cache
|
// First check cache
|
||||||
|
@ -283,15 +306,20 @@ bool DnsResolver::Resolve(const char *hostname, IpAddr *result) {
|
||||||
if (token_.is_cancelled())
|
if (token_.is_cancelled())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
RINFO("Unable to resolve %s. Trying again in %d second(s)", hostname, retry_delays[attempt]);
|
RINFO("Unable to resolve %s. Trying again in %d second(s)", hostname, retry_delays[retry_attempt_]);
|
||||||
if (!InterruptibleSleep(retry_delays[attempt] * 1000, &token_))
|
if (!InterruptibleSleep(retry_delays[retry_attempt_] * 1000, &token_))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (attempt != ARRAY_SIZE(retry_delays) - 1)
|
if (retry_attempt_ != ARRAY_SIZE(retry_delays) - 1)
|
||||||
attempt++;
|
retry_attempt_++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DnsResolver::RetryNow() {
|
||||||
|
retry_attempt_ = 0;
|
||||||
|
token_.CancelSleepOnce();
|
||||||
|
}
|
||||||
|
|
||||||
// Parse an IPV4 address into sin, doing NAT64 translation if applicable (on IOS)
|
// Parse an IPV4 address into sin, doing NAT64 translation if applicable (on IOS)
|
||||||
static bool ParseIpv4WithNAT64Translation(const char *s, IpAddr *sin, int flags) {
|
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
|
// First verify it's actually a valid ipv4 address to prevent getaddrinfo from doing a slow resolve
|
||||||
|
|
Loading…
Reference in a new issue