summaryrefslogtreecommitdiff
path: root/libs/libcurl/src/asyn-ares.c
diff options
context:
space:
mode:
Diffstat (limited to 'libs/libcurl/src/asyn-ares.c')
-rw-r--r--libs/libcurl/src/asyn-ares.c149
1 files changed, 89 insertions, 60 deletions
diff --git a/libs/libcurl/src/asyn-ares.c b/libs/libcurl/src/asyn-ares.c
index ffb4ecd367..f13ccb36cb 100644
--- a/libs/libcurl/src/asyn-ares.c
+++ b/libs/libcurl/src/asyn-ares.c
@@ -60,13 +60,13 @@
#include "progress.h"
#include "timediff.h"
-# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
- defined(WIN32)
-# define CARES_STATICLIB
-# endif
-# include <ares.h>
-# include <ares_version.h> /* really old c-ares didn't include this by
- itself */
+#if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
+ defined(_WIN32)
+# define CARES_STATICLIB
+#endif
+#include <ares.h>
+#include <ares_version.h> /* really old c-ares didn't include this by
+ itself */
#if ARES_VERSION >= 0x010500
/* c-ares 1.5.0 or later, the callback proto is modified */
@@ -228,9 +228,9 @@ static void destroy_async_data(struct Curl_async *async);
void Curl_resolver_cancel(struct Curl_easy *data)
{
DEBUGASSERT(data);
- if(data->state.async.resolver)
- ares_cancel((ares_channel)data->state.async.resolver);
- destroy_async_data(&data->state.async);
+ if(data->conn->resolve_async.resolver)
+ ares_cancel((ares_channel)data->conn->resolve_async.resolver);
+ destroy_async_data(&data->conn->resolve_async);
}
/*
@@ -278,14 +278,14 @@ int Curl_resolver_getsock(struct Curl_easy *data,
struct timeval timebuf;
struct timeval *timeout;
long milli;
- int max = ares_getsock((ares_channel)data->state.async.resolver,
+ int max = ares_getsock((ares_channel)data->conn->resolve_async.resolver,
(ares_socket_t *)socks, MAX_SOCKSPEREASYHANDLE);
maxtime.tv_sec = CURL_TIMEOUT_RESOLVE;
maxtime.tv_usec = 0;
- timeout = ares_timeout((ares_channel)data->state.async.resolver, &maxtime,
- &timebuf);
+ timeout = ares_timeout((ares_channel)data->conn->resolve_async.resolver,
+ &maxtime, &timebuf);
milli = (long)curlx_tvtoms(timeout);
if(milli == 0)
milli += 10;
@@ -313,8 +313,8 @@ static int waitperform(struct Curl_easy *data, timediff_t timeout_ms)
int i;
int num = 0;
- bitmask = ares_getsock((ares_channel)data->state.async.resolver, socks,
- ARES_GETSOCK_MAXNUM);
+ bitmask = ares_getsock((ares_channel)data->conn->resolve_async.resolver,
+ socks, ARES_GETSOCK_MAXNUM);
for(i = 0; i < ARES_GETSOCK_MAXNUM; i++) {
pfd[i].events = 0;
@@ -344,12 +344,12 @@ static int waitperform(struct Curl_easy *data, timediff_t timeout_ms)
if(!nfds)
/* Call ares_process() unconditionally here, even if we simply timed out
above, as otherwise the ares name resolve won't timeout! */
- ares_process_fd((ares_channel)data->state.async.resolver, ARES_SOCKET_BAD,
- ARES_SOCKET_BAD);
+ ares_process_fd((ares_channel)data->conn->resolve_async.resolver,
+ ARES_SOCKET_BAD, ARES_SOCKET_BAD);
else {
/* move through the descriptors and ask for processing on them */
for(i = 0; i < num; i++)
- ares_process_fd((ares_channel)data->state.async.resolver,
+ ares_process_fd((ares_channel)data->conn->resolve_async.resolver,
(pfd[i].revents & (POLLRDNORM|POLLIN))?
pfd[i].fd:ARES_SOCKET_BAD,
(pfd[i].revents & (POLLWRNORM|POLLOUT))?
@@ -368,7 +368,7 @@ static int waitperform(struct Curl_easy *data, timediff_t timeout_ms)
CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
struct Curl_dns_entry **dns)
{
- struct thread_data *res = data->state.async.tdata;
+ struct thread_data *res = data->conn->resolve_async.tdata;
CURLcode result = CURLE_OK;
DEBUGASSERT(dns);
@@ -397,7 +397,7 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
ARES_ECANCELLED synchronously for all pending responses. This will
leave us with res->num_pending == 0, which is perfect for the next
block. */
- ares_cancel((ares_channel)data->state.async.resolver);
+ ares_cancel((ares_channel)data->conn->resolve_async.resolver);
DEBUGASSERT(res->num_pending == 0);
}
#endif
@@ -408,12 +408,12 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
them */
res->temp_ai = NULL;
- if(!data->state.async.dns)
+ if(!data->conn->resolve_async.dns)
result = Curl_resolver_error(data);
else
- *dns = data->state.async.dns;
+ *dns = data->conn->resolve_async.dns;
- destroy_async_data(&data->state.async);
+ destroy_async_data(&data->conn->resolve_async);
}
return result;
@@ -464,7 +464,8 @@ CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
store.tv_sec = itimeout/1000;
store.tv_usec = (itimeout%1000)*1000;
- tvp = ares_timeout((ares_channel)data->state.async.resolver, &store, &tv);
+ tvp = ares_timeout((ares_channel)data->conn->resolve_async.resolver,
+ &store, &tv);
/* use the timeout period ares returned to us above if less than one
second is left, otherwise just use 1000ms to make sure the progress
@@ -478,7 +479,7 @@ CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
return CURLE_UNRECOVERABLE_POLL;
result = Curl_resolver_is_resolved(data, entry);
- if(result || data->state.async.done)
+ if(result || data->conn->resolve_async.done)
break;
if(Curl_pgrsUpdate(data))
@@ -499,12 +500,12 @@ CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
}
if(result)
/* failure, so we cancel the ares operation */
- ares_cancel((ares_channel)data->state.async.resolver);
+ ares_cancel((ares_channel)data->conn->resolve_async.resolver);
/* Operation complete, if the lookup was successful we now have the entry
in the cache. */
if(entry)
- *entry = data->state.async.dns;
+ *entry = data->conn->resolve_async.dns;
if(result)
/* close the connection, since we can't return failure here without
@@ -571,12 +572,13 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */
be valid so only defer it when we know the 'status' says its fine! */
return;
- res = data->state.async.tdata;
+ res = data->conn->resolve_async.tdata;
if(res) {
res->num_pending--;
if(CURL_ASYNC_SUCCESS == status) {
- struct Curl_addrinfo *ai = Curl_he2ai(hostent, data->state.async.port);
+ struct Curl_addrinfo *ai = Curl_he2ai(hostent,
+ data->conn->resolve_async.port);
if(ai) {
compound_results(res, ai);
}
@@ -727,14 +729,16 @@ static void addrinfo_cb(void *arg, int status, int timeouts,
struct ares_addrinfo *result)
{
struct Curl_easy *data = (struct Curl_easy *)arg;
- struct thread_data *res = data->state.async.tdata;
- (void)timeouts;
- if(ARES_SUCCESS == status) {
- res->temp_ai = ares2addr(result->nodes);
- res->last_status = CURL_ASYNC_SUCCESS;
- ares_freeaddrinfo(result);
+ if(data->conn) {
+ struct thread_data *res = data->conn->resolve_async.tdata;
+ (void)timeouts;
+ if(ARES_SUCCESS == status) {
+ res->temp_ai = ares2addr(result->nodes);
+ res->last_status = CURL_ASYNC_SUCCESS;
+ ares_freeaddrinfo(result);
+ }
+ res->num_pending--;
}
- res->num_pending--;
}
#endif
@@ -755,15 +759,15 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
size_t namelen = strlen(hostname);
*waitp = 0; /* default to synchronous response */
- res = calloc(sizeof(struct thread_data) + namelen, 1);
+ res = calloc(1, sizeof(struct thread_data) + namelen);
if(res) {
strcpy(res->hostname, hostname);
- data->state.async.hostname = res->hostname;
- data->state.async.port = port;
- data->state.async.done = FALSE; /* not done */
- data->state.async.status = 0; /* clear */
- data->state.async.dns = NULL; /* clear */
- data->state.async.tdata = res;
+ data->conn->resolve_async.hostname = res->hostname;
+ data->conn->resolve_async.port = port;
+ data->conn->resolve_async.done = FALSE; /* not done */
+ data->conn->resolve_async.status = 0; /* clear */
+ data->conn->resolve_async.dns = NULL; /* clear */
+ data->conn->resolve_async.tdata = res;
/* initial status - failed */
res->last_status = ARES_ENOTFOUND;
@@ -793,8 +797,8 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
hints.ai_flags = ARES_AI_NUMERICSERV;
msnprintf(service, sizeof(service), "%d", port);
res->num_pending = 1;
- ares_getaddrinfo((ares_channel)data->state.async.resolver, hostname,
- service, &hints, addrinfo_cb, data);
+ ares_getaddrinfo((ares_channel)data->conn->resolve_async.resolver,
+ hostname, service, &hints, addrinfo_cb, data);
}
#else
@@ -804,10 +808,10 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
res->num_pending = 2;
/* areschannel is already setup in the Curl_open() function */
- ares_gethostbyname((ares_channel)data->state.async.resolver, hostname,
- PF_INET, query_completed_cb, data);
- ares_gethostbyname((ares_channel)data->state.async.resolver, hostname,
- PF_INET6, query_completed_cb, data);
+ ares_gethostbyname((ares_channel)data->conn->resolve_async.resolver,
+ hostname, PF_INET, query_completed_cb, data);
+ ares_gethostbyname((ares_channel)data->conn->resolve_async.resolver,
+ hostname, PF_INET6, query_completed_cb, data);
}
else
#endif
@@ -815,7 +819,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
res->num_pending = 1;
/* areschannel is already setup in the Curl_open() function */
- ares_gethostbyname((ares_channel)data->state.async.resolver,
+ ares_gethostbyname((ares_channel)data->conn->resolve_async.resolver,
hostname, PF_INET,
query_completed_cb, data);
}
@@ -829,6 +833,7 @@ CURLcode Curl_set_dns_servers(struct Curl_easy *data,
char *servers)
{
CURLcode result = CURLE_NOT_BUILT_IN;
+ ares_channel channel, lchannel = NULL;
int ares_result;
/* If server is NULL or empty, this would purge all DNS servers
@@ -841,11 +846,23 @@ CURLcode Curl_set_dns_servers(struct Curl_easy *data,
return CURLE_OK;
#ifdef HAVE_CARES_SERVERS_CSV
+ if(data->conn)
+ channel = data->conn->resolve_async.resolver;
+ else {
+ /* we are called by setopt on a data without a connection (yet). In that
+ * case we set the value on a local instance for checking.
+ * The configured data options are set when the connection for this
+ * transfer is created. */
+ result = Curl_resolver_init(data, (void **)&lchannel);
+ if(result)
+ goto out;
+ channel = lchannel;
+ }
+
#ifdef HAVE_CARES_PORTS_CSV
- ares_result = ares_set_servers_ports_csv(data->state.async.resolver,
- servers);
+ ares_result = ares_set_servers_ports_csv(channel, servers);
#else
- ares_result = ares_set_servers_csv(data->state.async.resolver, servers);
+ ares_result = ares_set_servers_csv(channel, servers);
#endif
switch(ares_result) {
case ARES_SUCCESS:
@@ -861,6 +878,9 @@ CURLcode Curl_set_dns_servers(struct Curl_easy *data,
result = CURLE_BAD_FUNCTION_ARGUMENT;
break;
}
+out:
+ if(lchannel)
+ Curl_resolver_cleanup(lchannel);
#else /* too old c-ares version! */
(void)data;
(void)(ares_result);
@@ -872,11 +892,14 @@ CURLcode Curl_set_dns_interface(struct Curl_easy *data,
const char *interf)
{
#ifdef HAVE_CARES_LOCAL_DEV
- if(!interf)
- interf = "";
-
- ares_set_local_dev((ares_channel)data->state.async.resolver, interf);
+ if(data->conn) {
+ /* not a setopt test run, set the value */
+ if(!interf)
+ interf = "";
+ ares_set_local_dev((ares_channel)data->conn->resolve_async.resolver,
+ interf);
+ }
return CURLE_OK;
#else /* c-ares version too old! */
(void)data;
@@ -900,8 +923,11 @@ CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data,
}
}
- ares_set_local_ip4((ares_channel)data->state.async.resolver,
- ntohl(a4.s_addr));
+ if(data->conn) {
+ /* not a setopt test run, set the value */
+ ares_set_local_ip4((ares_channel)data->conn->resolve_async.resolver,
+ ntohl(a4.s_addr));
+ }
return CURLE_OK;
#else /* c-ares version too old! */
@@ -927,7 +953,10 @@ CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data,
}
}
- ares_set_local_ip6((ares_channel)data->state.async.resolver, a6);
+ if(data->conn) {
+ /* not a setopt test run, set the value */
+ ares_set_local_ip6((ares_channel)data->conn->resolve_async.resolver, a6);
+ }
return CURLE_OK;
#else /* c-ares version too old! */