mirror of
https://github.com/curl/curl.git
synced 2026-07-24 11:47:16 +03:00
hostip: cache negative name resolves
Hold them for half the normal lifetime. Helps when told to transfer N URLs in quick succession that all use the same non-resolving hostname. Done by storing a DNS entry with a NULL pointer for 'addr'. Previously an attempt was made in #12406 by Björn Stenberg that was ultimately never merged. Closes #18157
This commit is contained in:
parent
06c12cc08b
commit
df2b4ccc22
11 changed files with 155 additions and 19 deletions
|
|
@ -368,6 +368,14 @@ static CURLcode async_rr_start(struct Curl_easy *data)
|
|||
thrdd->rr.channel = NULL;
|
||||
return CURLE_FAILED_INIT;
|
||||
}
|
||||
#ifdef CURLDEBUG
|
||||
if(getenv("CURL_DNS_SERVER")) {
|
||||
const char *servers = getenv("CURL_DNS_SERVER");
|
||||
status = ares_set_servers_ports_csv(thrdd->rr.channel, servers);
|
||||
if(status)
|
||||
return CURLE_FAILED_INIT;
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(&thrdd->rr.hinfo, 0, sizeof(thrdd->rr.hinfo));
|
||||
thrdd->rr.hinfo.port = -1;
|
||||
|
|
@ -375,6 +383,7 @@ static CURLcode async_rr_start(struct Curl_easy *data)
|
|||
data->conn->host.name, ARES_CLASS_IN,
|
||||
ARES_REC_TYPE_HTTPS,
|
||||
async_thrdd_rr_done, data, NULL);
|
||||
CURL_TRC_DNS(data, "Issued HTTPS-RR request for %s", data->conn->host.name);
|
||||
return CURLE_OK;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
33
lib/hostip.c
33
lib/hostip.c
|
|
@ -202,6 +202,8 @@ dnscache_entry_is_stale(void *datap, void *hc)
|
|||
if(dns->timestamp.tv_sec || dns->timestamp.tv_usec) {
|
||||
/* get age in milliseconds */
|
||||
timediff_t age = curlx_timediff(prune->now, dns->timestamp);
|
||||
if(!dns->addr)
|
||||
age *= 2; /* negative entries age twice as fast */
|
||||
if(age >= prune->max_age_ms)
|
||||
return TRUE;
|
||||
if(age > prune->oldest_ms)
|
||||
|
|
@ -798,6 +800,28 @@ static bool can_resolve_ip_version(struct Curl_easy *data, int ip_version)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static CURLcode store_negative_resolve(struct Curl_easy *data,
|
||||
const char *host,
|
||||
int port)
|
||||
{
|
||||
struct Curl_dnscache *dnscache = dnscache_get(data);
|
||||
struct Curl_dns_entry *dns;
|
||||
DEBUGASSERT(dnscache);
|
||||
if(!dnscache)
|
||||
return CURLE_FAILED_INIT;
|
||||
|
||||
/* put this new host in the cache */
|
||||
dns = dnscache_add_addr(data, dnscache, NULL, host, 0, port, FALSE);
|
||||
if(dns) {
|
||||
/* release the returned reference; the cache itself will keep the
|
||||
* entry alive: */
|
||||
dns->refcount--;
|
||||
infof(data, "Store negative name resolve for %s:%d", host, port);
|
||||
return CURLE_OK;
|
||||
}
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_resolv() is the main name resolve function within libcurl. It resolves
|
||||
* a name and returns a pointer to the entry in the 'entry' argument (if one
|
||||
|
|
@ -917,6 +941,11 @@ out:
|
|||
* or `respwait` is set for an async operation.
|
||||
* Everything else is a failure to resolve. */
|
||||
if(dns) {
|
||||
if(!dns->addr) {
|
||||
infof(data, "Negative DNS entry");
|
||||
dns->refcount--;
|
||||
return CURLE_COULDNT_RESOLVE_HOST;
|
||||
}
|
||||
*entry = dns;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
|
@ -942,6 +971,7 @@ error:
|
|||
Curl_resolv_unlink(data, &dns);
|
||||
*entry = NULL;
|
||||
Curl_async_shutdown(data);
|
||||
store_negative_resolve(data, hostname, port);
|
||||
return CURLE_COULDNT_RESOLVE_HOST;
|
||||
}
|
||||
|
||||
|
|
@ -1523,6 +1553,9 @@ CURLcode Curl_resolv_check(struct Curl_easy *data,
|
|||
result = Curl_async_is_resolved(data, dns);
|
||||
if(*dns)
|
||||
show_resolve_info(data, *dns);
|
||||
if(result)
|
||||
store_negative_resolve(data, data->state.async.hostname,
|
||||
data->state.async.port);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue