dnscache: slight refactoring

Slight refactoring around dnscache, e.g. hostcache

- eliminate `data->state.hostcache`. Always look up
  relevant dnscache at share/multi.
- unify naming to "dnscache", replacing "hostcache"
- use `struct Curl_dnscache`, even though it just
  contains a `Curl_hash` for now.
- add `Curl_dnscache_destroy()` for cleanup in
  share/multi.

Closes #16941
This commit is contained in:
Stefan Eissing 2025-04-03 13:11:32 +02:00 committed by Daniel Stenberg
parent 6140a574de
commit 01e76702ac
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
14 changed files with 217 additions and 255 deletions

View file

@ -317,8 +317,6 @@ static void cshutdn_terminate_all(struct cshutdn *cshutdn,
}
DEBUGASSERT(!Curl_llist_count(&cshutdn->list));
Curl_hostcache_clean(data, data->dns.hostcache);
sigpipe_restore(&pipe_st);
}

View file

@ -1229,20 +1229,9 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
return result;
}
if(data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
/* we got a response, store it in the cache */
dns = Curl_cache_addr(data, ai, dohp->host, 0, dohp->port, FALSE);
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
if(!dns) {
/* returned failure, bail out nicely */
Curl_freeaddrinfo(ai);
}
else {
if(dns) {
data->state.async.dns = dns;
*dnsp = dns;
result = CURLE_OK; /* address resolution OK */

View file

@ -72,18 +72,11 @@ CURLcode Curl_addrinfo_callback(struct Curl_easy *data,
if(CURL_ASYNC_SUCCESS == status) {
if(ai) {
if(data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
dns = Curl_cache_addr(data, ai,
data->conn->host.dispname, 0,
data->state.async.port, FALSE);
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
if(!dns) {
/* failed to store, cleanup and return error */
Curl_freeaddrinfo(ai);
/* failed to store, return error */
result = CURLE_OUT_OF_MEMORY;
}
}

View file

@ -119,7 +119,7 @@
* CURLRES_* defines based on the config*.h and curl_setup.h defines.
*/
static void hostcache_unlink_entry(void *entry);
static void dnscache_entry_free(struct Curl_dns_entry *dns);
#ifndef CURL_DISABLE_VERBOSE_STRINGS
static void show_resolve_info(struct Curl_easy *data,
@ -166,9 +166,9 @@ void Curl_printable_address(const struct Curl_addrinfo *ai, char *buf,
* the DNS caching. Without alloc. Return length of the id string.
*/
static size_t
create_hostcache_id(const char *name,
size_t nlen, /* 0 or actual name length */
int port, char *ptr, size_t buflen)
create_dnscache_id(const char *name,
size_t nlen, /* 0 or actual name length */
int port, char *ptr, size_t buflen)
{
size_t len = nlen ? nlen : strlen(name);
DEBUGASSERT(buflen >= MAX_HOSTCACHE_LEN);
@ -179,7 +179,7 @@ create_hostcache_id(const char *name,
return msnprintf(&ptr[len], 7, ":%u", port) + len;
}
struct hostcache_prune_data {
struct dnscache_prune_data {
time_t now;
time_t oldest; /* oldest time in cache not pruned. */
int max_age_sec;
@ -193,10 +193,10 @@ struct hostcache_prune_data {
* cache.
*/
static int
hostcache_entry_is_stale(void *datap, void *hc)
dnscache_entry_is_stale(void *datap, void *hc)
{
struct hostcache_prune_data *prune =
(struct hostcache_prune_data *) datap;
struct dnscache_prune_data *prune =
(struct dnscache_prune_data *) datap;
struct Curl_dns_entry *dns = (struct Curl_dns_entry *) hc;
if(dns->timestamp) {
@ -215,10 +215,10 @@ hostcache_entry_is_stale(void *datap, void *hc)
* Returns the 'age' of the oldest still kept entry.
*/
static time_t
hostcache_prune(struct Curl_hash *hostcache, int cache_timeout,
time_t now)
dnscache_prune(struct Curl_hash *hostcache, int cache_timeout,
time_t now)
{
struct hostcache_prune_data user;
struct dnscache_prune_data user;
user.max_age_sec = cache_timeout;
user.now = now;
@ -226,33 +226,56 @@ hostcache_prune(struct Curl_hash *hostcache, int cache_timeout,
Curl_hash_clean_with_criterium(hostcache,
(void *) &user,
hostcache_entry_is_stale);
dnscache_entry_is_stale);
return user.oldest;
}
static struct Curl_dnscache *dnscache_get(struct Curl_easy *data)
{
if(data->share && data->share->specifier & (1 << CURL_LOCK_DATA_DNS))
return &data->share->dnscache;
if(data->multi)
return &data->multi->dnscache;
return NULL;
}
static void dnscache_lock(struct Curl_easy *data,
struct Curl_dnscache *dnscache)
{
if(data->share && dnscache == &data->share->dnscache)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
}
static void dnscache_unlock(struct Curl_easy *data,
struct Curl_dnscache *dnscache)
{
if(data->share && dnscache == &data->share->dnscache)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
}
/*
* Library-wide function for pruning the DNS cache. This function takes and
* returns the appropriate locks.
*/
void Curl_hostcache_prune(struct Curl_easy *data)
void Curl_dnscache_prune(struct Curl_easy *data)
{
struct Curl_dnscache *dnscache = dnscache_get(data);
time_t now;
/* the timeout may be set -1 (forever) */
int timeout = data->set.dns_cache_timeout;
if(!data->dns.hostcache)
if(!dnscache)
/* NULL hostcache means we cannot do it */
return;
if(data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
dnscache_lock(data, dnscache);
now = time(NULL);
do {
/* Remove outdated and unused entries from the hostcache */
time_t oldest = hostcache_prune(data->dns.hostcache, timeout, now);
time_t oldest = dnscache_prune(&dnscache->entries, timeout, now);
if(oldest < INT_MAX)
timeout = (int)oldest; /* we know it fits */
@ -262,10 +285,9 @@ void Curl_hostcache_prune(struct Curl_easy *data)
/* if the cache size is still too big, use the oldest age as new
prune limit */
} while(timeout &&
(Curl_hash_count(data->dns.hostcache) > MAX_DNS_CACHE_SIZE));
(Curl_hash_count(&dnscache->entries) > MAX_DNS_CACHE_SIZE));
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
dnscache_unlock(data, dnscache);
}
#ifdef USE_ALARM_TIMEOUT
@ -278,39 +300,44 @@ static curl_simple_lock curl_jmpenv_lock;
/* lookup address, returns entry if found and not stale */
static struct Curl_dns_entry *fetch_addr(struct Curl_easy *data,
struct Curl_dnscache *dnscache,
const char *hostname,
int port)
{
struct Curl_dns_entry *dns = NULL;
char entry_id[MAX_HOSTCACHE_LEN];
size_t entry_len;
if(!dnscache)
return NULL;
/* Create an entry id, based upon the hostname and port */
size_t entry_len = create_hostcache_id(hostname, 0, port,
entry_id, sizeof(entry_id));
entry_len = create_dnscache_id(hostname, 0, port,
entry_id, sizeof(entry_id));
/* See if it is already in our dns cache */
dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
dns = Curl_hash_pick(&dnscache->entries, entry_id, entry_len + 1);
/* No entry found in cache, check if we might have a wildcard entry */
if(!dns && data->state.wildcard_resolve) {
entry_len = create_hostcache_id("*", 1, port, entry_id, sizeof(entry_id));
entry_len = create_dnscache_id("*", 1, port, entry_id, sizeof(entry_id));
/* See if it is already in our dns cache */
dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
dns = Curl_hash_pick(&dnscache->entries, entry_id, entry_len + 1);
}
if(dns && (data->set.dns_cache_timeout != -1)) {
/* See whether the returned entry is stale. Done before we release lock */
struct hostcache_prune_data user;
struct dnscache_prune_data user;
user.now = time(NULL);
user.max_age_sec = data->set.dns_cache_timeout;
user.oldest = 0;
if(hostcache_entry_is_stale(&user, dns)) {
if(dnscache_entry_is_stale(&user, dns)) {
infof(data, "Hostname in DNS cache was stale, zapped");
dns = NULL; /* the memory deallocation is being handled by the hash */
Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1);
Curl_hash_delete(&dnscache->entries, entry_id, entry_len + 1);
}
}
@ -336,7 +363,7 @@ static struct Curl_dns_entry *fetch_addr(struct Curl_easy *data,
if(!found) {
infof(data, "Hostname in DNS cache does not have needed family, zapped");
dns = NULL; /* the memory deallocation is being handled by the hash */
Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1);
Curl_hash_delete(&dnscache->entries, entry_id, entry_len + 1);
}
}
return dns;
@ -361,18 +388,16 @@ Curl_fetch_addr(struct Curl_easy *data,
const char *hostname,
int port)
{
struct Curl_dnscache *dnscache = dnscache_get(data);
struct Curl_dns_entry *dns = NULL;
if(data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
dns = fetch_addr(data, hostname, port);
dnscache_lock(data, dnscache);
dns = fetch_addr(data, dnscache, hostname, port);
if(dns)
dns->refcount++; /* we use it! */
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
dnscache_unlock(data, dnscache);
return dns;
}
@ -459,6 +484,70 @@ UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data,
}
#endif
static struct Curl_dns_entry *
dnscache_add_addr(struct Curl_easy *data,
struct Curl_dnscache *dnscache,
struct Curl_addrinfo *addr,
const char *hostname,
size_t hostlen, /* length or zero */
int port,
bool permanent)
{
char entry_id[MAX_HOSTCACHE_LEN];
size_t entry_len;
struct Curl_dns_entry *dns;
struct Curl_dns_entry *dns2;
#ifndef CURL_DISABLE_SHUFFLE_DNS
/* shuffle addresses if requested */
if(data->set.dns_shuffle_addresses) {
CURLcode result = Curl_shuffle_addr(data, &addr);
if(result) {
Curl_freeaddrinfo(addr);
return NULL;
}
}
#endif
if(!hostlen)
hostlen = strlen(hostname);
/* Create a new cache entry */
dns = calloc(1, sizeof(struct Curl_dns_entry) + hostlen);
if(!dns) {
Curl_freeaddrinfo(addr);
return NULL;
}
/* Create an entry id, based upon the hostname and port */
entry_len = create_dnscache_id(hostname, hostlen, port,
entry_id, sizeof(entry_id));
dns->refcount = 1; /* the cache has the first reference */
dns->addr = addr; /* this is the address(es) */
if(permanent)
dns->timestamp = 0; /* an entry that never goes stale */
else {
dns->timestamp = time(NULL);
if(dns->timestamp == 0)
dns->timestamp = 1;
}
dns->hostport = port;
if(hostlen)
memcpy(dns->hostname, hostname, hostlen);
/* Store the resolved data in our DNS cache. */
dns2 = Curl_hash_add(&dnscache->entries, entry_id, entry_len + 1,
(void *)dns);
if(!dns2) {
dnscache_entry_free(dns);
return NULL;
}
dns = dns2;
dns->refcount++; /* mark entry as in-use */
return dns;
}
/*
* Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache.
*
@ -476,55 +565,18 @@ Curl_cache_addr(struct Curl_easy *data,
int port,
bool permanent)
{
char entry_id[MAX_HOSTCACHE_LEN];
size_t entry_len;
struct Curl_dnscache *dnscache = dnscache_get(data);
struct Curl_dns_entry *dns;
struct Curl_dns_entry *dns2;
#ifndef CURL_DISABLE_SHUFFLE_DNS
/* shuffle addresses if requested */
if(data->set.dns_shuffle_addresses) {
CURLcode result = Curl_shuffle_addr(data, &addr);
if(result)
return NULL;
}
#endif
if(!hostlen)
hostlen = strlen(hostname);
/* Create a new cache entry */
dns = calloc(1, sizeof(struct Curl_dns_entry) + hostlen);
if(!dns) {
if(!dnscache) {
Curl_freeaddrinfo(addr);
return NULL;
}
/* Create an entry id, based upon the hostname and port */
entry_len = create_hostcache_id(hostname, hostlen, port,
entry_id, sizeof(entry_id));
dns->refcount = 1; /* the cache has the first reference */
dns->addr = addr; /* this is the address(es) */
if(permanent)
dns->timestamp = 0; /* an entry that never goes stale */
else {
dns->timestamp = time(NULL);
if(dns->timestamp == 0)
dns->timestamp = 1;
}
dns->hostport = port;
if(hostlen)
memcpy(dns->hostname, hostname, hostlen);
/* Store the resolved data in our DNS cache. */
dns2 = Curl_hash_add(data->dns.hostcache, entry_id, entry_len + 1,
(void *)dns);
if(!dns2) {
free(dns);
return NULL;
}
dns = dns2;
dns->refcount++; /* mark entry as in-use */
dnscache_lock(data, dnscache);
dns = dnscache_add_addr(data, dnscache, addr,
hostname, hostlen, port, permanent);
dnscache_unlock(data, dnscache);
return dns;
}
@ -694,6 +746,7 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
bool allowDOH,
struct Curl_dns_entry **entry)
{
struct Curl_dnscache *dnscache = dnscache_get(data);
struct Curl_dns_entry *dns = NULL;
CURLcode result;
enum resolve_t rc = CURLRESOLV_ERROR; /* default to failure */
@ -713,10 +766,12 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
(void)allowDOH;
#endif
if(data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
if(!dnscache)
return CURLRESOLV_ERROR;
dns = fetch_addr(data, hostname, port);
dnscache_lock(data, dnscache);
dns = fetch_addr(data, dnscache, hostname, port);
if(dns) {
infof(data, "Hostname %s was found in DNS cache", hostname);
@ -724,8 +779,7 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
rc = CURLRESOLV_RESOLVED;
}
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
dnscache_unlock(data, dnscache);
if(!dns) {
/* The entry was not in the cache. Resolve it to IP address */
@ -838,19 +892,9 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
}
}
else {
if(data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
/* we got a response, store it in the cache */
dns = Curl_cache_addr(data, addr, hostname, 0, port, FALSE);
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
if(!dns)
/* returned failure, bail out nicely */
Curl_freeaddrinfo(addr);
else {
if(dns) {
rc = CURLRESOLV_RESOLVED;
show_resolve_info(data, dns);
}
@ -1055,6 +1099,18 @@ clean_up:
return rc;
}
static void dnscache_entry_free(struct Curl_dns_entry *dns)
{
Curl_freeaddrinfo(dns->addr);
#ifdef USE_HTTPSRR
if(dns->hinfo) {
Curl_httpsrr_cleanup(dns->hinfo);
free(dns->hinfo);
}
#endif
free(dns);
}
/*
* Curl_resolv_unlink() releases a reference to the given cached DNS entry.
* When the reference count reaches 0, the entry is destroyed. It is important
@ -1064,71 +1120,48 @@ clean_up:
*/
void Curl_resolv_unlink(struct Curl_easy *data, struct Curl_dns_entry **pdns)
{
struct Curl_dnscache *dnscache = dnscache_get(data);
struct Curl_dns_entry *dns = *pdns;
*pdns = NULL;
if(data && data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
hostcache_unlink_entry(dns);
if(data && data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
dnscache_lock(data, dnscache);
dns->refcount--;
if(dns->refcount == 0)
dnscache_entry_free(dns);
dnscache_unlock(data, dnscache);
}
/*
* File-internal: release cache dns entry reference, free if inuse drops to 0
*/
static void hostcache_unlink_entry(void *entry)
static void dnscache_entry_dtor(void *entry)
{
struct Curl_dns_entry *dns = (struct Curl_dns_entry *) entry;
DEBUGASSERT(dns && (dns->refcount > 0));
dns->refcount--;
if(dns->refcount == 0) {
Curl_freeaddrinfo(dns->addr);
#ifdef USE_HTTPSRR
if(dns->hinfo) {
Curl_httpsrr_cleanup(dns->hinfo);
free(dns->hinfo);
}
#endif
free(dns);
}
if(dns->refcount == 0)
dnscache_entry_free(dns);
}
/*
* Curl_init_dnscache() inits a new DNS cache.
* Curl_dnscache_init() inits a new DNS cache.
*/
void Curl_init_dnscache(struct Curl_hash *hash, size_t size)
void Curl_dnscache_init(struct Curl_dnscache *dns, size_t size)
{
Curl_hash_init(hash, size, Curl_hash_str, Curl_str_key_compare,
hostcache_unlink_entry);
Curl_hash_init(&dns->entries, size, Curl_hash_str, Curl_str_key_compare,
dnscache_entry_dtor);
}
/*
* Curl_hostcache_clean()
*
* This _can_ be called with 'data' == NULL but then of course no locking
* can be done!
*/
void Curl_hostcache_clean(struct Curl_easy *data,
struct Curl_hash *hash)
void Curl_dnscache_destroy(struct Curl_dnscache *dns)
{
if(data && data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
Curl_hash_clean(hash);
if(data && data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
Curl_hash_destroy(&dns->entries);
}
CURLcode Curl_loadhostpairs(struct Curl_easy *data)
{
struct Curl_dnscache *dnscache = dnscache_get(data);
struct curl_slist *hostp;
if(!dnscache)
return CURLE_FAILED_INIT;
/* Default is no wildcard found */
data->state.wildcard_resolve = FALSE;
@ -1157,17 +1190,13 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
if(!Curl_str_number(&host, &num, 0xffff)) {
/* Create an entry id, based upon the hostname and port */
entry_len = create_hostcache_id(Curl_str(&source),
Curl_strlen(&source), (int)num,
entry_id, sizeof(entry_id));
if(data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
entry_len = create_dnscache_id(Curl_str(&source),
Curl_strlen(&source), (int)num,
entry_id, sizeof(entry_id));
dnscache_lock(data, dnscache);
/* delete entry, ignore if it did not exist */
Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1);
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
Curl_hash_delete(&dnscache->entries, entry_id, entry_len + 1);
dnscache_unlock(data, dnscache);
}
}
else {
@ -1268,15 +1297,14 @@ err:
}
/* Create an entry id, based upon the hostname and port */
entry_len = create_hostcache_id(Curl_str(&source), Curl_strlen(&source),
(int)port,
entry_id, sizeof(entry_id));
entry_len = create_dnscache_id(Curl_str(&source), Curl_strlen(&source),
(int)port,
entry_id, sizeof(entry_id));
if(data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
dnscache_lock(data, dnscache);
/* See if it is already in our dns cache */
dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
dns = Curl_hash_pick(&dnscache->entries, entry_id, entry_len + 1);
if(dns) {
infof(data, "RESOLVE %.*s:%" CURL_FORMAT_CURL_OFF_T
@ -1293,25 +1321,23 @@ err:
4. when adding a non-permanent entry, we want it to get a "fresh"
timeout that starts _now_. */
Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1);
Curl_hash_delete(&dnscache->entries, entry_id, entry_len + 1);
}
/* put this new host in the cache */
dns = Curl_cache_addr(data, head, Curl_str(&source),
Curl_strlen(&source), (int)port, permanent);
dns = dnscache_add_addr(data, dnscache, head, Curl_str(&source),
Curl_strlen(&source), (int)port, permanent);
if(dns) {
/* release the returned reference; the cache itself will keep the
* entry alive: */
dns->refcount--;
}
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
dnscache_unlock(data, dnscache);
if(!dns) {
Curl_freeaddrinfo(head);
if(!dns)
return CURLE_OUT_OF_MEMORY;
}
#ifndef CURL_DISABLE_VERBOSE_STRINGS
infof(data, "Added %.*s:%" CURL_FORMAT_CURL_OFF_T ":%s to DNS cache%s",
(int)Curl_strlen(&source), Curl_str(&source), port, addresses,

View file

@ -61,15 +61,6 @@ enum alpnid {
ALPN_h3 = CURLALTSVC_H3
};
/*
* Curl_global_host_cache_init() initializes and sets up a global DNS cache.
* Global DNS cache is general badness. Do not use. This will be removed in
* a future version. Use the share interface instead!
*
* Returns a struct Curl_hash pointer on success, NULL on failure.
*/
struct Curl_hash *Curl_global_host_cache_init(void);
struct Curl_dns_entry {
struct Curl_addrinfo *addr;
#ifdef USE_HTTPSRR
@ -85,6 +76,10 @@ struct Curl_dns_entry {
char hostname[1];
};
struct Curl_dnscache {
struct Curl_hash entries;
};
bool Curl_host_is_ipnum(const char *hostname);
/*
@ -144,10 +139,12 @@ void Curl_resolv_unlink(struct Curl_easy *data,
struct Curl_dns_entry **pdns);
/* init a new dns cache */
void Curl_init_dnscache(struct Curl_hash *hash, size_t hashsize);
void Curl_dnscache_init(struct Curl_dnscache *dns, size_t hashsize);
void Curl_dnscache_destroy(struct Curl_dnscache *dns);
/* prune old entries from the DNS cache */
void Curl_hostcache_prune(struct Curl_easy *data);
void Curl_dnscache_prune(struct Curl_easy *data);
/* IPv4 threadsafe resolve function used for synch and asynch builds */
struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, int port);
@ -156,7 +153,7 @@ CURLcode Curl_once_resolved(struct Curl_easy *data, bool *protocol_connect);
/*
* Curl_addrinfo_callback() is used when we build with any asynch specialty.
* Handles end of async request processing. Inserts ai into hostcache when
* Handles end of async request processing. Inserts ai into dnscache when
* status is CURL_ASYNC_SUCCESS. Twiddles fields in conn to indicate async
* request completed whether successful or failed.
*/
@ -187,6 +184,7 @@ Curl_fetch_addr(struct Curl_easy *data,
/*
* Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache.
* Call takes ownership of `addr` and free's it on failure.
* @param permanent iff TRUE, entry will never become stale
* Returns the Curl_dns_entry entry pointer or NULL if the storage failed.
*/
@ -221,11 +219,6 @@ CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data,
CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data,
const char *local_ip6);
/*
* Clean off entries from the cache
*/
void Curl_hostcache_clean(struct Curl_easy *data, struct Curl_hash *hash);
/*
* Populate the cache with specified entries from CURLOPT_RESOLVE.
*/

View file

@ -221,7 +221,7 @@ struct Curl_multi *Curl_multi_handle(size_t ev_hashsize, /* event hash */
multi->magic = CURL_MULTI_HANDLE;
Curl_init_dnscache(&multi->hostcache, dnssize);
Curl_dnscache_init(&multi->dnscache, dnssize);
Curl_multi_ev_init(multi, ev_hashsize);
Curl_hash_init(&multi->proto_hash, 23,
@ -275,7 +275,7 @@ error:
Curl_multi_ev_cleanup(multi);
Curl_hash_destroy(&multi->proto_hash);
Curl_hash_destroy(&multi->hostcache);
Curl_dnscache_destroy(&multi->dnscache);
Curl_cpool_destroy(&multi->cpool);
Curl_cshutdn_destroy(&multi->cshutdn, multi->admin);
Curl_ssl_scache_destroy(multi->ssl_scache);
@ -382,14 +382,6 @@ CURLMcode curl_multi_add_handle(CURLM *m, CURL *d)
/* set the easy handle */
multistate(data, MSTATE_INIT);
/* for multi interface connections, we share DNS cache automatically if the
easy handle's one is currently not set. */
if(!data->dns.hostcache ||
(data->dns.hostcachetype == HCACHE_NONE)) {
data->dns.hostcache = &multi->hostcache;
data->dns.hostcachetype = HCACHE_MULTI;
}
#ifdef USE_LIBPSL
/* Do the same for PSL. */
if(data->share && (data->share->specifier & (1 << CURL_LOCK_DATA_PSL)))
@ -468,7 +460,7 @@ static void multi_done_locked(struct connectdata *conn,
if(conn->dns_entry)
Curl_resolv_unlink(data, &conn->dns_entry); /* done with this */
Curl_hostcache_prune(data);
Curl_dnscache_prune(data);
/* if data->set.reuse_forbid is TRUE, it means the libcurl client has
forced us to close this connection. This is ignored for requests taking
@ -682,13 +674,6 @@ CURLMcode curl_multi_remove_handle(CURLM *m, CURL *d)
/* the handle is in a list, remove it from whichever it is */
Curl_node_remove(&data->multi_queue);
if(data->dns.hostcachetype == HCACHE_MULTI) {
/* stop using the multi handle's DNS cache, *after* the possible
multi_done() call above */
data->dns.hostcache = NULL;
data->dns.hostcachetype = HCACHE_NONE;
}
Curl_wildcard_dtor(&data->wildcard);
data->mstate = MSTATE_COMPLETED;
@ -2711,12 +2696,6 @@ CURLMcode curl_multi_cleanup(CURLM *m)
if(!data->state.done && data->conn)
/* if DONE was never called for this handle */
(void)multi_done(data, CURLE_OK, TRUE);
if(data->dns.hostcachetype == HCACHE_MULTI) {
/* clear out the usage of the shared DNS cache */
Curl_hostcache_clean(data, data->dns.hostcache);
data->dns.hostcache = NULL;
data->dns.hostcachetype = HCACHE_NONE;
}
data->multi = NULL; /* clear the association */
@ -2738,7 +2717,7 @@ CURLMcode curl_multi_cleanup(CURLM *m)
Curl_multi_ev_cleanup(multi);
Curl_hash_destroy(&multi->proto_hash);
Curl_hash_destroy(&multi->hostcache);
Curl_dnscache_destroy(&multi->dnscache);
Curl_psl_destroy(&multi->psl);
Curl_ssl_scache_destroy(multi->ssl_scache);

View file

@ -28,6 +28,7 @@
#include "hash.h"
#include "conncache.h"
#include "cshutdn.h"
#include "hostip.h"
#include "multi_ev.h"
#include "psl.h"
#include "socketpair.h"
@ -111,7 +112,7 @@ struct Curl_multi {
curl_push_callback push_cb;
void *push_userp;
struct Curl_hash hostcache; /* Hostname cache */
struct Curl_dnscache dnscache; /* DNS cache */
struct Curl_ssl_scache *ssl_scache; /* TLS session pool */
#ifdef USE_LIBPSL

View file

@ -1569,11 +1569,6 @@ static CURLcode setopt_pointers(struct Curl_easy *data, CURLoption option,
if(data->share) {
Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
if(data->dns.hostcachetype == HCACHE_SHARED) {
data->dns.hostcache = NULL;
data->dns.hostcachetype = HCACHE_NONE;
}
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
if(data->share->cookies == data->cookies)
data->cookies = NULL;
@ -1603,11 +1598,6 @@ static CURLcode setopt_pointers(struct Curl_easy *data, CURLoption option,
data->share->dirty++;
if(data->share->specifier & (1 << CURL_LOCK_DATA_DNS)) {
/* use shared host cache */
data->dns.hostcache = &data->share->hostcache;
data->dns.hostcachetype = HCACHE_SHARED;
}
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
if(data->share->cookies) {
/* use shared cookie list, first free own one if any */

View file

@ -46,7 +46,7 @@ curl_share_init(void)
if(share) {
share->magic = CURL_GOOD_SHARE;
share->specifier |= (1 << CURL_LOCK_DATA_SHARE);
Curl_init_dnscache(&share->hostcache, 23);
Curl_dnscache_init(&share->dnscache, 23);
share->admin = curl_easy_init();
if(!share->admin) {
free(share);
@ -247,7 +247,8 @@ curl_share_cleanup(CURLSH *sh)
if(share->specifier & (1 << CURL_LOCK_DATA_CONNECT)) {
Curl_cpool_destroy(&share->cpool);
}
Curl_hash_destroy(&share->hostcache);
Curl_dnscache_destroy(&share->dnscache);
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
Curl_cookie_cleanup(share->cookies);

View file

@ -51,7 +51,7 @@ struct Curl_share {
void *clientdata;
struct Curl_easy *admin;
struct cpool cpool;
struct Curl_hash hostcache;
struct Curl_dnscache dnscache; /* DNS cache */
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
struct CookieInfo *cookies;
#endif

View file

@ -1840,15 +1840,6 @@ struct UserDefined {
#define IS_MIME_POST(a) FALSE
#endif
struct Names {
struct Curl_hash *hostcache;
enum {
HCACHE_NONE, /* not pointing to anything */
HCACHE_MULTI, /* points to a shared one in the multi handle */
HCACHE_SHARED /* points to a shared one in a shared object */
} hostcachetype;
};
/*
* The 'connectdata' struct MUST have all the connection oriented stuff as we
* may have several simultaneous connections and connection structs in memory.
@ -1884,7 +1875,6 @@ struct Curl_easy {
struct Curl_message msg; /* A single posted message. */
struct Names dns;
struct Curl_multi *multi; /* if non-NULL, points to the multi handle
struct to which this "belongs" when used by
the multi interface */

View file

@ -41,7 +41,7 @@
#include "memdebug.h" /* LAST include file */
static struct Curl_easy *testdata;
static struct Curl_hash hp;
static struct Curl_dnscache hp;
static char *data_key;
static struct Curl_dns_entry *data_node;
@ -53,7 +53,7 @@ static CURLcode unit_setup(void)
return CURLE_OUT_OF_MEMORY;
}
Curl_init_dnscache(&hp, 7);
Curl_dnscache_init(&hp, 7);
return CURLE_OK;
}
@ -64,7 +64,7 @@ static void unit_stop(void)
free(data_node);
}
free(data_key);
Curl_hash_destroy(&hp);
Curl_dnscache_destroy(&hp);
curl_easy_cleanup(testdata);
curl_global_cleanup();
@ -122,7 +122,7 @@ UNITTEST_START
key_len = strlen(data_key);
data_node->refcount = 1; /* hash will hold the reference */
nodep = Curl_hash_add(&hp, data_key, key_len + 1, data_node);
nodep = Curl_hash_add(&hp.entries, data_key, key_len + 1, data_node);
abort_unless(nodep, "insertion into hash failed");
/* Freeing will now be done by Curl_hash_destroy */
data_node = NULL;

View file

@ -139,7 +139,8 @@ UNITTEST_START
entry_id = (void *)aprintf("%s:%d", tests[i].host, tests[i].port);
if(!entry_id)
goto error;
dns = Curl_hash_pick(easy->dns.hostcache, entry_id, strlen(entry_id) + 1);
dns = Curl_hash_pick(&multi->dnscache.entries,
entry_id, strlen(entry_id) + 1);
free(entry_id);
entry_id = NULL;

View file

@ -141,7 +141,8 @@ UNITTEST_START
if(!entry_id)
goto error;
dns = Curl_hash_pick(easy->dns.hostcache, entry_id, strlen(entry_id) + 1);
dns = Curl_hash_pick(&multi->dnscache.entries,
entry_id, strlen(entry_id) + 1);
free(entry_id);
entry_id = NULL;