]> granicus.if.org Git - curl/commitdiff
CURLOPT_RESOLVE: avoid adding already present host names
authorDaniel Stenberg <daniel@haxx.se>
Sat, 31 Dec 2011 09:28:10 +0000 (10:28 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Sat, 31 Dec 2011 09:45:27 +0000 (10:45 +0100)
The load host names to DNS cache function was moved to hostip.c and it
now makes sure to not add host names that already are present in the
cache. It would previously lead to memory leaks when for example using
the --resolve and multiple URLs on the command line.

lib/hostip.c
lib/hostip.h
lib/transfer.c

index 44ed0a42480b9e9bdbb3d180047b300353d1ce09..03c3bc981a3eca28b45496cd5506c9f298e2aa94 100644 (file)
@@ -743,3 +743,69 @@ void Curl_hostcache_destroy(struct SessionHandle *data)
   data->dns.hostcachetype = HCACHE_NONE;
   data->dns.hostcache = NULL;
 }
+
+CURLcode Curl_loadhostpairs(struct SessionHandle *data)
+{
+  struct curl_slist *hostp;
+  char hostname[256];
+  char address[256];
+  int port;
+
+  for(hostp = data->change.resolve; hostp; hostp = hostp->next ) {
+    if(!hostp->data)
+      continue;
+    if(hostp->data[0] == '-') {
+      /* TODO: mark an entry for removal */
+    }
+    else if(3 == sscanf(hostp->data, "%255[^:]:%d:%255s", hostname, &port,
+                        address)) {
+      struct Curl_dns_entry *dns;
+      Curl_addrinfo *addr;
+      char *entry_id;
+      size_t entry_len;
+
+      addr = Curl_str2addr(address, port);
+      if(!addr) {
+        infof(data, "Resolve %s found illegal!\n", hostp->data);
+        continue;
+      }
+
+      /* Create an entry id, based upon the hostname and port */
+      entry_id = create_hostcache_id(hostname, port);
+      /* If we can't create the entry id, fail */
+      if(!entry_id)
+        return CURLE_OUT_OF_MEMORY;
+
+      entry_len = strlen(entry_id);
+
+      if(data->share)
+        Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
+
+      /* See if its already in our dns cache */
+      dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len+1);
+
+      /* free the allocated entry_id again */
+      free(entry_id);
+
+      if(!dns)
+        /* if not in the cache already, put this host in the cache */
+        dns = Curl_cache_addr(data, addr, hostname, port);
+      else
+        /* this is a duplicate, free it again */
+        Curl_freeaddrinfo(addr);
+
+      if(data->share)
+        Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
+
+      if(!dns) {
+        Curl_freeaddrinfo(addr);
+        return CURLE_OUT_OF_MEMORY;
+      }
+      infof(data, "Added %s:%d:%s to DNS cache\n",
+            hostname, port, address);
+    }
+  }
+  data->change.resolve = NULL; /* dealt with now */
+
+  return CURLE_OK;
+}
index 100bdc58e10b6a30afded87930f42537c6ec02fb..12fb80f547f2540f4601f89293d4ea5741578626 100644 (file)
@@ -205,4 +205,6 @@ CURLcode Curl_set_dns_servers(struct SessionHandle *data, char *servers);
  */
 void Curl_hostcache_destroy(struct SessionHandle *data);
 
+CURLcode Curl_loadhostpairs(struct SessionHandle *data);
+
 #endif /* HEADER_CURL_HOSTIP_H */
index 21bf2464c91b47a5c547a6ef46df83fb05681522..9f05cfbd77d3d40639dcb4b4fb2c7eacc2445461 100644 (file)
@@ -1405,52 +1405,6 @@ Transfer(struct connectdata *conn)
   return CURLE_OK;
 }
 
-static CURLcode loadhostpairs(struct SessionHandle *data)
-{
-  struct curl_slist *hostp;
-  char hostname[256];
-  char address[256];
-  int port;
-
-  for(hostp = data->change.resolve; hostp; hostp = hostp->next ) {
-    if(!hostp->data)
-      continue;
-    if(hostp->data[0] == '-') {
-      /* TODO: mark an entry for removal */
-    }
-    else if(3 == sscanf(hostp->data, "%255[^:]:%d:%255s", hostname, &port,
-                        address)) {
-      struct Curl_dns_entry *dns;
-      Curl_addrinfo *addr;
-
-      addr = Curl_str2addr(address, port);
-      if(!addr) {
-        infof(data, "Resolve %s found illegal!\n", hostp->data);
-        continue;
-      }
-
-      if(data->share)
-        Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
-
-      /* put this host in the cache */
-      dns = Curl_cache_addr(data, addr, hostname, port);
-
-      if(data->share)
-        Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
-
-      if(!dns) {
-        Curl_freeaddrinfo(addr);
-        return CURLE_OUT_OF_MEMORY;
-      }
-      infof(data, "Added %s:%d:%s to DNS cache\n",
-            hostname, port, address);
-    }
-  }
-  data->change.resolve = NULL; /* dealt with now */
-
-  return CURLE_OK;
-}
-
 
 /*
  * Curl_pretransfer() is called immediately before a transfer starts.
@@ -1490,7 +1444,7 @@ CURLcode Curl_pretransfer(struct SessionHandle *data)
 
   /* If there is a list of host pairs to deal with */
   if(data->change.resolve)
-    res = loadhostpairs(data);
+    res = Curl_loadhostpairs(data);
 
   if(!res) {
     /* Allow data->set.use_port to set which port to use. This needs to be