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.c134
1 files changed, 70 insertions, 64 deletions
diff --git a/libs/libcurl/src/asyn-ares.c b/libs/libcurl/src/asyn-ares.c
index 0ef36cbbe2..38ede999ce 100644
--- a/libs/libcurl/src/asyn-ares.c
+++ b/libs/libcurl/src/asyn-ares.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, 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
- * are also available at http://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
@@ -22,6 +22,14 @@
#include "curl_setup.h"
+/***********************************************************************
+ * Only for ares-enabled builds
+ * And only for functions that fulfill the asynch resolver backend API
+ * as defined in asyn.h, nothing else belongs in this file!
+ **********************************************************************/
+
+#ifdef CURLRES_ARES
+
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
@@ -48,14 +56,6 @@
#define in_addr_t unsigned long
#endif
-/***********************************************************************
- * Only for ares-enabled builds
- * And only for functions that fulfill the asynch resolver backend API
- * as defined in asyn.h, nothing else belongs in this file!
- **********************************************************************/
-
-#ifdef CURLRES_ARES
-
#include "urldata.h"
#include "sendf.h"
#include "hostip.h"
@@ -69,9 +69,6 @@
#include "select.h"
#include "progress.h"
-#define _MPRINTF_REPLACE /* use our functions only */
-#include <curl/mprintf.h>
-
# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
(defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__))
# define CARES_STATICLIB
@@ -85,8 +82,9 @@
#define HAVE_CARES_CALLBACK_TIMEOUTS 1
#endif
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
#include "curl_memory.h"
-/* The last #include file should be: */
#include "memdebug.h"
struct ResolverResults {
@@ -166,19 +164,19 @@ void Curl_resolver_cleanup(void *resolver)
int Curl_resolver_duphandle(void **to, void *from)
{
/* Clone the ares channel for the new handle */
- if(ARES_SUCCESS != ares_dup((ares_channel*)to,(ares_channel)from))
+ if(ARES_SUCCESS != ares_dup((ares_channel*)to, (ares_channel)from))
return CURLE_FAILED_INIT;
return CURLE_OK;
}
-static void destroy_async_data (struct Curl_async *async);
+static void destroy_async_data(struct Curl_async *async);
/*
* Cancel all possibly still on-going resolves for this connection.
*/
void Curl_resolver_cancel(struct connectdata *conn)
{
- if(conn && conn->data && conn->data->state.resolver)
+ if(conn->data && conn->data->state.resolver)
ares_cancel((ares_channel)conn->data->state.resolver);
destroy_async_data(&conn->async);
}
@@ -186,10 +184,9 @@ void Curl_resolver_cancel(struct connectdata *conn)
/*
* destroy_async_data() cleans up async resolver data.
*/
-static void destroy_async_data (struct Curl_async *async)
+static void destroy_async_data(struct Curl_async *async)
{
- if(async->hostname)
- free(async->hostname);
+ free(async->hostname);
if(async->os_specific) {
struct ResolverResults *res = (struct ResolverResults *)async->os_specific;
@@ -235,7 +232,7 @@ int Curl_resolver_getsock(struct connectdata *conn,
milli = (timeout->tv_sec * 1000) + (timeout->tv_usec/1000);
if(milli == 0)
milli += 10;
- Curl_expire(conn->data, milli);
+ Curl_expire(conn->data, milli, EXPIRE_ASYNC_NAME);
return max;
}
@@ -252,7 +249,7 @@ int Curl_resolver_getsock(struct connectdata *conn,
static int waitperform(struct connectdata *conn, int timeout_ms)
{
- struct SessionHandle *data = conn->data;
+ struct Curl_easy *data = conn->data;
int nfds;
int bitmask;
ares_socket_t socks[ARES_GETSOCK_MAXNUM];
@@ -263,7 +260,7 @@ static int waitperform(struct connectdata *conn, int timeout_ms)
bitmask = ares_getsock((ares_channel)data->state.resolver, socks,
ARES_GETSOCK_MAXNUM);
- for(i=0; i < ARES_GETSOCK_MAXNUM; i++) {
+ for(i = 0; i < ARES_GETSOCK_MAXNUM; i++) {
pfd[i].events = 0;
pfd[i].revents = 0;
if(ARES_GETSOCK_READABLE(bitmask, i)) {
@@ -292,7 +289,7 @@ static int waitperform(struct connectdata *conn, int timeout_ms)
ARES_SOCKET_BAD);
else {
/* move through the descriptors and ask for processing on them */
- for(i=0; i < num; i++)
+ for(i = 0; i < num; i++)
ares_process_fd((ares_channel)data->state.resolver,
pfd[i].revents & (POLLRDNORM|POLLIN)?
pfd[i].fd:ARES_SOCKET_BAD,
@@ -312,10 +309,10 @@ static int waitperform(struct connectdata *conn, int timeout_ms)
CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
struct Curl_dns_entry **dns)
{
- struct SessionHandle *data = conn->data;
+ struct Curl_easy *data = conn->data;
struct ResolverResults *res = (struct ResolverResults *)
conn->async.os_specific;
- CURLcode rc = CURLE_OK;
+ CURLcode result = CURLE_OK;
*dns = NULL;
@@ -329,7 +326,7 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
if(!conn->async.dns) {
failf(data, "Could not resolve: %s (%s)",
conn->async.hostname, ares_strerror(conn->async.status));
- rc = conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
+ result = conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
CURLE_COULDNT_RESOLVE_HOST;
}
else
@@ -338,7 +335,7 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
destroy_async_data(&conn->async);
}
- return rc;
+ return result;
}
/*
@@ -355,20 +352,27 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
struct Curl_dns_entry **entry)
{
- CURLcode rc=CURLE_OK;
- struct SessionHandle *data = conn->data;
- long timeout;
- struct timeval now = Curl_tvnow();
+ CURLcode result = CURLE_OK;
+ struct Curl_easy *data = conn->data;
+ timediff_t timeout;
+ struct curltime now = Curl_now();
struct Curl_dns_entry *temp_entry;
+ if(entry)
+ *entry = NULL; /* clear on entry */
+
timeout = Curl_timeleft(data, &now, TRUE);
+ if(timeout < 0) {
+ /* already expired! */
+ connclose(conn, "Timed out before name resolve started");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
if(!timeout)
timeout = CURL_TIMEOUT_RESOLVE * 1000; /* default name resolve timeout */
/* Wait for the name resolve query to complete. */
- for(;;) {
+ while(!result) {
struct timeval *tvp, tv, store;
- long timediff;
int itimeout;
int timeout_ms;
@@ -388,42 +392,44 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
timeout_ms = 1000;
waitperform(conn, timeout_ms);
- Curl_resolver_is_resolved(conn,&temp_entry);
+ result = Curl_resolver_is_resolved(conn, &temp_entry);
- if(conn->async.done)
+ if(result || conn->async.done)
break;
- if(Curl_pgrsUpdate(conn)) {
- rc = CURLE_ABORTED_BY_CALLBACK;
- timeout = -1; /* trigger the cancel below */
- }
+ if(Curl_pgrsUpdate(conn))
+ result = CURLE_ABORTED_BY_CALLBACK;
else {
- struct timeval now2 = Curl_tvnow();
- timediff = Curl_tvdiff(now2, now); /* spent time */
- timeout -= timediff?timediff:1; /* always deduct at least 1 */
+ struct curltime now2 = Curl_now();
+ timediff_t timediff = Curl_timediff(now2, now); /* spent time */
+ if(timediff <= 0)
+ timeout -= 1; /* always deduct at least 1 */
+ else if(timediff > timeout)
+ timeout = -1;
+ else
+ timeout -= (long)timediff;
now = now2; /* for next loop */
}
- if(timeout < 0) {
- /* our timeout, so we cancel the ares operation */
- ares_cancel((ares_channel)data->state.resolver);
- break;
- }
+ if(timeout < 0)
+ result = CURLE_OPERATION_TIMEDOUT;
}
+ if(result)
+ /* failure, so we cancel the ares operation */
+ ares_cancel((ares_channel)data->state.resolver);
/* Operation complete, if the lookup was successful we now have the entry
in the cache. */
-
if(entry)
*entry = conn->async.dns;
- if(rc)
+ if(result)
/* close the connection, since we can't return failure here without
cleaning up this connection properly.
TODO: remove this action from here, it is not a name resolver decision.
*/
- conn->bits.close = TRUE;
+ connclose(conn, "c-ares resolve failed");
- return rc;
+ return result;
}
/* Connects results to the list */
@@ -495,7 +501,7 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
int *waitp)
{
char *bufp;
- struct SessionHandle *data = conn->data;
+ struct Curl_easy *data = conn->data;
struct in_addr in;
int family = PF_INET;
#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */
@@ -536,15 +542,15 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
bufp = strdup(hostname);
if(bufp) {
struct ResolverResults *res = NULL;
- Curl_safefree(conn->async.hostname);
+ free(conn->async.hostname);
conn->async.hostname = bufp;
conn->async.port = port;
conn->async.done = FALSE; /* not done */
conn->async.status = 0; /* clear */
conn->async.dns = NULL; /* clear */
- res = calloc(sizeof(struct ResolverResults),1);
+ res = calloc(sizeof(struct ResolverResults), 1);
if(!res) {
- Curl_safefree(conn->async.hostname);
+ free(conn->async.hostname);
conn->async.hostname = NULL;
return NULL;
}
@@ -586,7 +592,7 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
return NULL; /* no struct yet */
}
-CURLcode Curl_set_dns_servers(struct SessionHandle *data,
+CURLcode Curl_set_dns_servers(struct Curl_easy *data,
char *servers)
{
CURLcode result = CURLE_NOT_BUILT_IN;
@@ -624,7 +630,7 @@ CURLcode Curl_set_dns_servers(struct SessionHandle *data,
return result;
}
-CURLcode Curl_set_dns_interface(struct SessionHandle *data,
+CURLcode Curl_set_dns_interface(struct Curl_easy *data,
const char *interf)
{
#if (ARES_VERSION >= 0x010704)
@@ -641,14 +647,14 @@ CURLcode Curl_set_dns_interface(struct SessionHandle *data,
#endif
}
-CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data,
+CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data,
const char *local_ip4)
{
#if (ARES_VERSION >= 0x010704)
- uint32_t a4;
+ struct in_addr a4;
if((!local_ip4) || (local_ip4[0] == 0)) {
- a4 = 0; /* disabled: do not bind to a specific address */
+ a4.s_addr = 0; /* disabled: do not bind to a specific address */
}
else {
if(Curl_inet_pton(AF_INET, local_ip4, &a4) != 1) {
@@ -656,7 +662,7 @@ CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data,
}
}
- ares_set_local_ip4((ares_channel)data->state.resolver, ntohl(a4));
+ ares_set_local_ip4((ares_channel)data->state.resolver, ntohl(a4.s_addr));
return CURLE_OK;
#else /* c-ares version too old! */
@@ -666,10 +672,10 @@ CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data,
#endif
}
-CURLcode Curl_set_dns_local_ip6(struct SessionHandle *data,
+CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data,
const char *local_ip6)
{
-#if (ARES_VERSION >= 0x010704)
+#if (ARES_VERSION >= 0x010704) && defined(ENABLE_IPV6)
unsigned char a6[INET6_ADDRSTRLEN];
if((!local_ip6) || (local_ip6[0] == 0)) {