Commit 22ac08e0 authored by Sterling Hughes's avatar Sterling Hughes
Browse files

Add support for DNS cache timeouts via the CURLOPT_DNS_CACHE_TIMEOUT option.

The default cache timeout for this is 60 seconds, which is arbitrary and
completely subject to change :)
parent 87037136
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -491,6 +491,9 @@ typedef enum {
  /* Non-zero value means to use the global dns cache */
  CINIT(DNS_USE_GLOBAL_CACHE, LONG, 91),

  /* DNS cache timeout */
  CINIT(DNS_CACHE_TIMEOUT, LONG, 92),
  
  CURLOPT_LASTENTRY /* the last unusued */
} CURLoption;

+50 −11
Original line number Diff line number Diff line
@@ -93,24 +93,59 @@ void Curl_global_host_cache_dtor(void)
  }
}

struct curl_dns_cache_entry {
  Curl_addrinfo *addr;
  int            timestamp;
};

Curl_addrinfo *Curl_resolv(struct SessionHandle *data,
                           char *hostname,
                           int port,
                           char **bufp)
{
  Curl_addrinfo *addr = NULL;
  size_t hostname_len = strlen(hostname)+1;
  struct curl_dns_cache_entry *p = NULL;
  size_t hostname_len;
  time_t now;

  /* If the host cache timeout is 0, we don't do DNS cach'ing
     so fall through */
  if (data->set.dns_cache_timeout == 0) {
    return Curl_getaddrinfo(data, hostname, port, bufp);
  }

  hostname_len = strlen(hostname)+1;

  time(&now);
  /* See if its already in our dns cache */
  if (curl_hash_find(data->hostcache, hostname, hostname_len, (void **) &p)) {
    /* Do we need to check for a cache timeout? */
    if (data->set.dns_cache_timeout != -1) {
      /* Return if the entry has not timed out */
      if ((now - p->timestamp) < data->set.dns_cache_timeout) {
        return p->addr;
      }
    }
    else {
      return p->addr;
    }
  }

  if (curl_hash_find(data->hostcache, hostname, hostname_len, (void **) &addr)) {
    return addr;
  /* Create a new cache entry */
  p = (struct curl_dns_cache_entry *) malloc(sizeof(struct curl_dns_cache_entry));
  if (!p) {
    return NULL;
  }

  addr = Curl_getaddrinfo(data, hostname, port, bufp);
  if (!addr)
  p->addr = Curl_getaddrinfo(data, hostname, port, bufp);
  if (!p->addr) {
    return NULL;
  }
  p->timestamp = now;

  curl_hash_add(data->hostcache, hostname, hostname_len, (const void *) addr);
  return addr;
  /* Save it in our host cache */
  curl_hash_update(data->hostcache, hostname, hostname_len, (const void *) p);

  return p->addr;
}

/*
@@ -120,11 +155,15 @@ Curl_addrinfo *Curl_resolv(struct SessionHandle *data,
 */
void Curl_freeaddrinfo(void *freethis)
{
  struct curl_dns_cache_entry *p = (struct curl_dns_cache_entry *) freethis;

#ifdef ENABLE_IPV6
  freeaddrinfo(freethis);
  freeaddrinfo(p->addr);
#else
  free(freethis);
  free(p->addr);
#endif

  free(p);
}

/* --- resolve name or IP-number --- */
+8 −2
Original line number Diff line number Diff line
@@ -251,6 +251,8 @@ CURLcode Curl_open(struct SessionHandle **curl)
  data->set.httpreq = HTTPREQ_GET; /* Default HTTP request */
  data->set.ftp_use_epsv = TRUE;   /* FTP defaults to EPSV operations */

  data->set.dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
  
  /* make libcurl quiet by default: */
  data->set.hide_progress = TRUE;  /* CURLOPT_NOPROGRESS changes these */
  data->progress.flags |= PGRS_HIDE;
@@ -284,7 +286,11 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
  va_start(param, option);

  switch(option) {
    case CURLOPT_DNS_USE_GLOBAL_CACHE: {
  case CURLOPT_DNS_CACHE_TIMEOUT:
    data->set.dns_cache_timeout = va_arg(param, int);
    break;
  case CURLOPT_DNS_USE_GLOBAL_CACHE: 
    {
      int use_cache = va_arg(param, int);
      if (use_cache) {
        Curl_global_host_cache_init();
+1 −0
Original line number Diff line number Diff line
@@ -647,6 +647,7 @@ struct UserDefined {
  bool ftp_use_epsv;     /* if EPSV is to be attempted or not */

  bool global_dns_cache;
  bool dns_cache_timeout;
};

/*