aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/curl/curl.h3
-rw-r--r--lib/easy.c18
-rw-r--r--lib/hash.c11
-rw-r--r--lib/hash.h1
-rw-r--r--lib/hostip.c26
-rw-r--r--lib/hostip.h9
-rw-r--r--lib/multi.c24
-rw-r--r--lib/url.c9
-rw-r--r--lib/urldata.h4
9 files changed, 89 insertions, 16 deletions
diff --git a/include/curl/curl.h b/include/curl/curl.h
index 11574175d..3d91c85ff 100644
--- a/include/curl/curl.h
+++ b/include/curl/curl.h
@@ -488,6 +488,9 @@ typedef enum {
*/
CINIT(SSLENGINE_DEFAULT, LONG, 90),
+ /* Non-zero value means to use the global dns cache */
+ CINIT(DNS_USE_GLOBAL_CACHE, LONG, 91),
+
CURLOPT_LASTENTRY /* the last unusued */
} CURLoption;
diff --git a/lib/easy.c b/lib/easy.c
index c24eb9018..45de7e8d5 100644
--- a/lib/easy.c
+++ b/lib/easy.c
@@ -141,8 +141,6 @@ CURLcode curl_global_init(long flags)
if (initialized)
return CURLE_OK;
- Curl_host_cache_init();
-
if (flags & CURL_GLOBAL_SSL)
Curl_SSL_init();
@@ -165,8 +163,8 @@ void curl_global_cleanup(void)
if (!initialized)
return;
- Curl_host_cache_dtor();
-
+ Curl_global_host_cache_dtor();
+
if (init_flags & CURL_GLOBAL_SSL)
Curl_SSL_cleanup();
@@ -235,12 +233,24 @@ CURLcode curl_easy_perform(CURL *curl)
{
struct SessionHandle *data = (struct SessionHandle *)curl;
+ if (!data->hostcache) {
+ if (Curl_global_host_cache_use(data)) {
+ data->hostcache = Curl_global_host_cache_get();
+ }
+ else {
+ data->hostcache = curl_hash_alloc(7, Curl_freeaddrinfo);
+ }
+ }
+
return Curl_perform(data);
}
void curl_easy_cleanup(CURL *curl)
{
struct SessionHandle *data = (struct SessionHandle *)curl;
+ if (!Curl_global_host_cache_use(data)) {
+ curl_hash_destroy(data->hostcache);
+ }
Curl_close(data);
}
diff --git a/lib/hash.c b/lib/hash.c
index c0680e488..1ed3cc21a 100644
--- a/lib/hash.c
+++ b/lib/hash.c
@@ -255,11 +255,22 @@ curl_hash_clean(curl_hash *h)
h->table = NULL;
}
+size_t
+curl_hash_count(curl_hash *h)
+{
+ return h->size;
+}
+
void
curl_hash_destroy(curl_hash *h)
{
+ if (!h) {
+ return;
+ }
+
curl_hash_clean(h);
free(h);
+ h = NULL;
}
/*
diff --git a/lib/hash.h b/lib/hash.h
index 420bb899f..66ef3dfeb 100644
--- a/lib/hash.h
+++ b/lib/hash.h
@@ -71,6 +71,7 @@ int curl_hash_extended_delete(curl_hash *h, char *str_key, unsigned int str_key_
int curl_hash_extended_find(curl_hash *h, char *str_key, unsigned int str_key_len,
unsigned long num_key, void **p);
void curl_hash_apply(curl_hash *h, void *user, void (*cb)(void *, curl_hash_element *));
+size_t curl_hash_count(curl_hash *h);
void curl_hash_clean(curl_hash *h);
void curl_hash_destroy(curl_hash *h);
diff --git a/lib/hostip.c b/lib/hostip.c
index db02b8681..791ee030c 100644
--- a/lib/hostip.c
+++ b/lib/hostip.c
@@ -70,17 +70,27 @@
#endif
static curl_hash hostname_cache;
+static int host_cache_initialized;
-void Curl_host_cache_init(void)
+void Curl_global_host_cache_init(void)
{
- curl_hash_init(&hostname_cache, 7, Curl_freeaddrinfo);
+ if (!host_cache_initialized) {
+ curl_hash_init(&hostname_cache, 7, Curl_freeaddrinfo);
+ host_cache_initialized = 1;
+ }
}
-void Curl_host_cache_dtor(void)
+curl_hash *Curl_global_host_cache_get(void)
{
- curl_hash_clean(&hostname_cache);
+ return &hostname_cache;
}
+void Curl_global_host_cache_dtor(void)
+{
+ if (host_cache_initialized) {
+ curl_hash_clean(&hostname_cache);
+ }
+}
Curl_addrinfo *Curl_resolv(struct SessionHandle *data,
char *hostname,
@@ -90,14 +100,15 @@ Curl_addrinfo *Curl_resolv(struct SessionHandle *data,
Curl_addrinfo *addr = NULL;
size_t hostname_len = strlen(hostname)+1;
- if (curl_hash_find(&hostname_cache, hostname, hostname_len, (void **) &addr))
+ if (curl_hash_find(data->hostcache, hostname, hostname_len, (void **) &addr)) {
return addr;
-
+ }
+
addr = Curl_getaddrinfo(data, hostname, port, bufp);
if (!addr)
return NULL;
- curl_hash_add(&hostname_cache, hostname, hostname_len, (const void *) addr);
+ curl_hash_add(data->hostcache, hostname, hostname_len, (const void *) addr);
return addr;
}
@@ -405,3 +416,4 @@ Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
* vim600: fdm=marker
* vim: et sw=2 ts=2 sts=2 tw=78
*/
+
diff --git a/lib/hostip.h b/lib/hostip.h
index 97b50ae9d..0cc98b605 100644
--- a/lib/hostip.h
+++ b/lib/hostip.h
@@ -23,12 +23,17 @@
* $Id$
*****************************************************************************/
+#include "hash.h"
+
struct addrinfo;
struct hostent;
struct SessionHandle;
-void Curl_host_cache_init(void);
-void Curl_host_cache_dtor(void);
+void Curl_global_host_cache_init(void);
+void Curl_global_host_cache_dtor(void);
+curl_hash *Curl_global_host_cache_get(void);
+
+#define Curl_global_host_cache_use(__p) ((__p)->set.global_dns_cache)
Curl_addrinfo *Curl_resolv(struct SessionHandle *data,
char *hostname,
diff --git a/lib/multi.c b/lib/multi.c
index b7ab209f5..bfd3949cb 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -82,7 +82,8 @@ struct Curl_multi {
struct Curl_message *msgs;
/* amount of messages in the queue */
int num_msgs;
-
+ /* Hostname cache */
+ curl_hash *hostcache;
};
@@ -244,7 +245,6 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
easy=multi->easy.next;
while(easy) {
-
switch(easy->state) {
case CURLM_STATE_INIT:
/* init this transfer. */
@@ -256,6 +256,17 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
}
break;
case CURLM_STATE_CONNECT:
+ if (Curl_global_host_cache_use(easy->easy_handle)) {
+ easy->easy_handle->hostcache = Curl_global_host_cache_get();
+ }
+ else {
+ if (multi->hostcache == NULL) {
+ multi->hostcache = curl_hash_alloc(7, Curl_freeaddrinfo);
+ }
+
+ easy->easy_handle->hostcache = multi->hostcache;
+ }
+
/* Connect. We get a connection identifier filled in. */
easy->result = Curl_connect(easy->easy_handle, &easy->easy_conn);
@@ -328,7 +339,7 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle)
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
if(GOOD_MULTI_HANDLE(multi)) {
multi->type = 0; /* not good anymore */
-
+ curl_hash_destroy(multi->hostcache);
/* remove all easy handles */
free(multi);
@@ -341,3 +352,10 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle)
CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue);
+/*
+ * local variables:
+ * eval: (load-file "../curl-mode.el")
+ * end:
+ * vim600: fdm=marker
+ * vim: et sw=2 ts=2 sts=2 tw=78
+ */
diff --git a/lib/url.c b/lib/url.c
index 5f7568005..56e7fa73f 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -284,6 +284,15 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
va_start(param, option);
switch(option) {
+ case CURLOPT_DNS_USE_GLOBAL_CACHE: {
+ int use_cache = va_arg(param, int);
+ if (use_cache) {
+ Curl_global_host_cache_init();
+ }
+
+ data->set.global_dns_cache = use_cache;
+ }
+ break;
case CURLOPT_SSL_CIPHER_LIST:
/* set a list of cipher we want to use in the SSL connection */
data->set.ssl.cipher_list = va_arg(param, char *);
diff --git a/lib/urldata.h b/lib/urldata.h
index b7f3a2f21..36358d60f 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -27,6 +27,7 @@
#include "setup.h"
#include "hostip.h"
+#include "hash.h"
#define PORT_FTP 21
#define PORT_TELNET 23
@@ -644,6 +645,8 @@ struct UserDefined {
bool reuse_fresh; /* do not re-use an existing connection */
bool expect100header; /* TRUE if we added Expect: 100-continue */
bool ftp_use_epsv; /* if EPSV is to be attempted or not */
+
+ bool global_dns_cache;
};
/*
@@ -658,6 +661,7 @@ struct UserDefined {
* 'struct urlstate' instead. */
struct SessionHandle {
+ curl_hash *hostcache;
struct UserDefined set; /* values set by the libcurl user */
struct DynamicStatic change; /* possibly modified userdefined data */