* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* hostip.c - method-independent resolver functions and utility functions
* hostasyn.c - functions for asynchronous name resolves
* hostsyn.c - functions for synchronous name resolves
- * hostip4.c - ipv4-specific functions
- * hostip6.c - ipv6-specific functions
+ * hostip4.c - IPv4 specific functions
+ * hostip6.c - IPv6 specific functions
*
* The two asynchronous name resolver backends are implemented in:
* asyn-ares.c - functions for ares-using name resolves
(struct hostcache_prune_data *) datap;
struct Curl_dns_entry *c = (struct Curl_dns_entry *) hc;
- return (data->now - c->timestamp >= data->cache_timeout);
+ return !c->inuse && (data->now - c->timestamp >= data->cache_timeout);
}
/*
{
struct hostcache_prune_data user;
- if(!dns || (data->set.dns_cache_timeout == -1) || !data->dns.hostcache)
- /* cache forever means never prune, and NULL hostcache means
- we can't do it */
+ if(!dns || (data->set.dns_cache_timeout == -1) || !data->dns.hostcache ||
+ dns->inuse)
+ /* cache forever means never prune, and NULL hostcache means we can't do
+ it, if it still is in use then we leave it */
return 0;
time(&user.now);
sigjmp_buf curl_jmpenv;
#endif
+/*
+ * Curl_fetch_addr() fetches a 'Curl_dns_entry' already in the DNS cache.
+ *
+ * Curl_resolv() checks initially and multi_runsingle() checks each time
+ * it discovers the handle in the state WAITRESOLVE whether the hostname
+ * has already been resolved and the address has already been stored in
+ * the DNS cache. This short circuits waiting for a lot of pending
+ * lookups for the same hostname requested by different handles.
+ *
+ * Returns the Curl_dns_entry entry pointer or NULL if not in the cache.
+ */
+struct Curl_dns_entry *
+Curl_fetch_addr(struct connectdata *conn,
+ const char *hostname,
+ int port)
+{
+ char *entry_id = NULL;
+ struct Curl_dns_entry *dns = NULL;
+ size_t entry_len;
+ struct SessionHandle *data = conn->data;
+ int stale;
+
+ /* 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 dns;
+
+ entry_len = strlen(entry_id);
+
+ /* 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);
+
+ /* See whether the returned entry is stale. Done before we release lock */
+ stale = remove_entry_if_stale(data, dns);
+ if(stale) {
+ infof(data, "Hostname in DNS cache was stale, zapped\n");
+ dns = NULL; /* the memory deallocation is being handled by the hash */
+ }
+
+ return dns;
+}
/*
* Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache.
int port,
struct Curl_dns_entry **entry)
{
- char *entry_id = NULL;
struct Curl_dns_entry *dns = NULL;
- size_t entry_len;
struct SessionHandle *data = conn->data;
CURLcode result;
int rc = CURLRESOLV_ERROR; /* default to failure */
*entry = NULL;
- /* 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 rc;
-
- 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);
-
- /* See whether the returned entry is stale. Done before we release lock */
- if(remove_entry_if_stale(data, dns))
- dns = NULL; /* the memory deallocation is being handled by the hash */
+ dns = Curl_fetch_addr(conn, hostname, port);
if(dns) {
+ infof(data, "Hostname %s was found in DNS cache\n", hostname);
dns->inuse++; /* we use it! */
rc = CURLRESOLV_RESOLVED;
}