From 01e76702aca1ef893d0e653a70b3261ae61899d3 Mon Sep 17 00:00:00 2001 From: Stefan Eissing Date: Thu, 3 Apr 2025 13:11:32 +0200 Subject: [PATCH] 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 --- lib/cshutdn.c | 2 - lib/doh.c | 13 +- lib/hostasyn.c | 9 +- lib/hostip.c | 302 +++++++++++++++++++++++------------------- lib/hostip.h | 27 ++-- lib/multi.c | 29 +--- lib/multihandle.h | 3 +- lib/setopt.c | 10 -- lib/share.c | 5 +- lib/share.h | 2 +- lib/urldata.h | 10 -- tests/unit/unit1305.c | 8 +- tests/unit/unit1607.c | 3 +- tests/unit/unit1609.c | 3 +- 14 files changed, 194 insertions(+), 232 deletions(-) diff --git a/lib/cshutdn.c b/lib/cshutdn.c index 9d4a5ec67a..45581bd081 100644 --- a/lib/cshutdn.c +++ b/lib/cshutdn.c @@ -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); } diff --git a/lib/doh.c b/lib/doh.c index dbeb6d71a3..def9781e47 100644 --- a/lib/doh.c +++ b/lib/doh.c @@ -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 */ diff --git a/lib/hostasyn.c b/lib/hostasyn.c index 44b1fe1bfa..6314f38351 100644 --- a/lib/hostasyn.c +++ b/lib/hostasyn.c @@ -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; } } diff --git a/lib/hostip.c b/lib/hostip.c index bef67c73bc..f658ac3a39 100644 --- a/lib/hostip.c +++ b/lib/hostip.c @@ -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,22 +484,14 @@ UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data, } #endif -/* - * Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache. - * - * When calling Curl_resolv() has resulted in a response with a returned - * address, we call this function to store the information in the dns - * cache etc - * - * Returns the Curl_dns_entry entry pointer or NULL if the storage failed. - */ -struct Curl_dns_entry * -Curl_cache_addr(struct Curl_easy *data, - struct Curl_addrinfo *addr, - const char *hostname, - size_t hostlen, /* length or zero */ - int port, - bool permanent) +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; @@ -485,8 +502,10 @@ Curl_cache_addr(struct Curl_easy *data, /* shuffle addresses if requested */ if(data->set.dns_shuffle_addresses) { CURLcode result = Curl_shuffle_addr(data, &addr); - if(result) + if(result) { + Curl_freeaddrinfo(addr); return NULL; + } } #endif if(!hostlen) @@ -495,12 +514,13 @@ Curl_cache_addr(struct Curl_easy *data, /* 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_hostcache_id(hostname, hostlen, port, - entry_id, sizeof(entry_id)); + 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) */ @@ -516,10 +536,10 @@ Curl_cache_addr(struct Curl_easy *data, 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, + dns2 = Curl_hash_add(&dnscache->entries, entry_id, entry_len + 1, (void *)dns); if(!dns2) { - free(dns); + dnscache_entry_free(dns); return NULL; } @@ -528,6 +548,38 @@ Curl_cache_addr(struct Curl_easy *data, return dns; } +/* + * Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache. + * + * When calling Curl_resolv() has resulted in a response with a returned + * address, we call this function to store the information in the dns + * cache etc + * + * Returns the Curl_dns_entry entry pointer or NULL if the storage failed. + */ +struct Curl_dns_entry * +Curl_cache_addr(struct Curl_easy *data, + struct Curl_addrinfo *addr, + const char *hostname, + size_t hostlen, /* length or zero */ + int port, + bool permanent) +{ + struct Curl_dnscache *dnscache = dnscache_get(data); + struct Curl_dns_entry *dns; + + if(!dnscache) { + Curl_freeaddrinfo(addr); + return NULL; + } + + dnscache_lock(data, dnscache); + dns = dnscache_add_addr(data, dnscache, addr, + hostname, hostlen, port, permanent); + dnscache_unlock(data, dnscache); + return dns; +} + #ifdef USE_IPV6 /* return a static IPv6 ::1 for the name */ static struct Curl_addrinfo *get_localhost6(int port, const char *name) @@ -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; + + dnscache_lock(data, dnscache); - dns = fetch_addr(data, hostname, port); + 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, diff --git a/lib/hostip.h b/lib/hostip.h index 931b40b681..f92d64a9cf 100644 --- a/lib/hostip.h +++ b/lib/hostip.h @@ -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. */ diff --git a/lib/multi.c b/lib/multi.c index 9f439652e2..02ec6b374f 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -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); diff --git a/lib/multihandle.h b/lib/multihandle.h index bc28e74754..d3d66074e9 100644 --- a/lib/multihandle.h +++ b/lib/multihandle.h @@ -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 diff --git a/lib/setopt.c b/lib/setopt.c index 48332295ed..e8fec8de8a 100644 --- a/lib/setopt.c +++ b/lib/setopt.c @@ -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 */ diff --git a/lib/share.c b/lib/share.c index ba3b4ae5af..721030f260 100644 --- a/lib/share.c +++ b/lib/share.c @@ -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); diff --git a/lib/share.h b/lib/share.h index 240e2b4a07..974c99dc20 100644 --- a/lib/share.h +++ b/lib/share.h @@ -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 diff --git a/lib/urldata.h b/lib/urldata.h index e4487ba657..890b36297f 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -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 */ diff --git a/tests/unit/unit1305.c b/tests/unit/unit1305.c index 03011a577a..3c0cbabca7 100644 --- a/tests/unit/unit1305.c +++ b/tests/unit/unit1305.c @@ -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; diff --git a/tests/unit/unit1607.c b/tests/unit/unit1607.c index 5b658eb02d..2904b4cce4 100644 --- a/tests/unit/unit1607.c +++ b/tests/unit/unit1607.c @@ -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; diff --git a/tests/unit/unit1609.c b/tests/unit/unit1609.c index c3b11d7a4d..45bc3cfcd8 100644 --- a/tests/unit/unit1609.c +++ b/tests/unit/unit1609.c @@ -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; -- 2.47.2