]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
dnscache: slight refactoring
authorStefan Eissing <stefan@eissing.org>
Thu, 3 Apr 2025 11:11:32 +0000 (13:11 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Thu, 3 Apr 2025 14:40:56 +0000 (16:40 +0200)
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

14 files changed:
lib/cshutdn.c
lib/doh.c
lib/hostasyn.c
lib/hostip.c
lib/hostip.h
lib/multi.c
lib/multihandle.h
lib/setopt.c
lib/share.c
lib/share.h
lib/urldata.h
tests/unit/unit1305.c
tests/unit/unit1607.c
tests/unit/unit1609.c

index 9d4a5ec67aea6e449855702d37a20f1cbcfc4dc4..45581bd081c4b66cdb3cc52de79ef46042273755 100644 (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);
 }
 
index dbeb6d71a3a55dc4304d1d82930ebde913a1ab24..def9781e474a69e9db6f4acf01a43d7e4ba27603 100644 (file)
--- 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 */
index 44b1fe1bfa2da5c9db8a94a0039d84fc29130b5c..6314f38351aa306b39d4e70e4fbf13bf51888555 100644 (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;
       }
     }
index bef67c73bc85613f22f365bfdd2cd2642e182931..f658ac3a39b9f860058620d8ad4c2b11f66ca6cc 100644 (file)
  * 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,
index 931b40b681239bff743e8994f95bca5f9e260c40..f92d64a9cf920ea0f47d30ea937a0f1a07beef70 100644 (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.
  */
index 9f439652e2701b318781914a8c337eb4f38f9609..02ec6b374f87327e7f939b87ce551f33487d01be 100644 (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);
 
index bc28e74754b079a88d940da2eeac2ee8612af8a8..d3d66074e951c07d67cb3863362f19f5677eb907 100644 (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
index 48332295ed1fdb383c0437d9efdf9e97959f0668..e8fec8de8a23aa913ed69c3e73f00d612c1b4794 100644 (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 */
index ba3b4ae5afb2ec9e1dd08e934ada35605ef2a62e..721030f2608e6b68112ff76a398ad17cffdc8416 100644 (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);
index 240e2b4a074d124073b9fe2ef251ba8db045cfc8..974c99dc204bb88fcaef1800c72340ba61d6e53b 100644 (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
index e4487ba6576d57b6b038cef1bbdd81a4365b1116..890b36297f7ecce23a0e685c942f811021a8f666 100644 (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 */
index 03011a577a9acfaeaffcc7724918ed98bf75d13a..3c0cbabca74e5a618244a1a61e2e06afaf6d1d38 100644 (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;
index 5b658eb02d05078a9579c93ecedebb576fefeaa7..2904b4cce4140b44cf7fffb6a103858096d87fbc 100644 (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;
 
index c3b11d7a4dac3e1c8c27e38aebee3e04562088ba..45bc3cfcd8b7f5ad0726008ecf09799483122b5a 100644 (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;