1
0
mirror of https://github.com/moparisthebest/curl synced 2024-12-24 09:08:49 -05:00

hostip: remove conn->data from resolver functions

This also moves the 'async' struct from the connectdata struct into the
Curl_easy struct, which seems like a better home for it.

Closes #6497
This commit is contained in:
Daniel Stenberg 2021-01-20 10:15:43 +01:00
parent d3a3bdb5ef
commit 8335c6417e
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
18 changed files with 242 additions and 254 deletions

View File

@ -204,22 +204,22 @@ static void destroy_async_data(struct Curl_async *async);
/* /*
* Cancel all possibly still on-going resolves for this connection. * Cancel all possibly still on-going resolves for this connection.
*/ */
void Curl_resolver_cancel(struct connectdata *conn) void Curl_resolver_cancel(struct Curl_easy *data)
{ {
if(conn->data && conn->data->state.resolver) if(data && data->state.async.resolver)
ares_cancel((ares_channel)conn->data->state.resolver); ares_cancel((ares_channel)data->state.async.resolver);
destroy_async_data(&conn->async); destroy_async_data(&data->state.async);
} }
/* /*
* We're equivalent to Curl_resolver_cancel() for the c-ares resolver. We * We're equivalent to Curl_resolver_cancel() for the c-ares resolver. We
* never block. * never block.
*/ */
void Curl_resolver_kill(struct connectdata *conn) void Curl_resolver_kill(struct Curl_easy *data)
{ {
/* We don't need to check the resolver state because we can be called safely /* We don't need to check the resolver state because we can be called safely
at any time and we always do the same thing. */ at any time and we always do the same thing. */
Curl_resolver_cancel(conn); Curl_resolver_cancel(data);
} }
/* /*
@ -253,25 +253,25 @@ static void destroy_async_data(struct Curl_async *async)
* Returns: sockets-in-use-bitmap * Returns: sockets-in-use-bitmap
*/ */
int Curl_resolver_getsock(struct connectdata *conn, int Curl_resolver_getsock(struct Curl_easy *data,
curl_socket_t *socks) curl_socket_t *socks)
{ {
struct timeval maxtime; struct timeval maxtime;
struct timeval timebuf; struct timeval timebuf;
struct timeval *timeout; struct timeval *timeout;
long milli; long milli;
int max = ares_getsock((ares_channel)conn->data->state.resolver, int max = ares_getsock((ares_channel)data->state.async.resolver,
(ares_socket_t *)socks, MAX_SOCKSPEREASYHANDLE); (ares_socket_t *)socks, MAX_SOCKSPEREASYHANDLE);
maxtime.tv_sec = CURL_TIMEOUT_RESOLVE; maxtime.tv_sec = CURL_TIMEOUT_RESOLVE;
maxtime.tv_usec = 0; maxtime.tv_usec = 0;
timeout = ares_timeout((ares_channel)conn->data->state.resolver, &maxtime, timeout = ares_timeout((ares_channel)data->state.async.resolver, &maxtime,
&timebuf); &timebuf);
milli = (timeout->tv_sec * 1000) + (timeout->tv_usec/1000); milli = (timeout->tv_sec * 1000) + (timeout->tv_usec/1000);
if(milli == 0) if(milli == 0)
milli += 10; milli += 10;
Curl_expire(conn->data, milli, EXPIRE_ASYNC_NAME); Curl_expire(data, milli, EXPIRE_ASYNC_NAME);
return max; return max;
} }
@ -286,9 +286,8 @@ int Curl_resolver_getsock(struct connectdata *conn,
* return number of sockets it worked on * return number of sockets it worked on
*/ */
static int waitperform(struct connectdata *conn, timediff_t timeout_ms) static int waitperform(struct Curl_easy *data, timediff_t timeout_ms)
{ {
struct Curl_easy *data = conn->data;
int nfds; int nfds;
int bitmask; int bitmask;
ares_socket_t socks[ARES_GETSOCK_MAXNUM]; ares_socket_t socks[ARES_GETSOCK_MAXNUM];
@ -296,7 +295,7 @@ static int waitperform(struct connectdata *conn, timediff_t timeout_ms)
int i; int i;
int num = 0; int num = 0;
bitmask = ares_getsock((ares_channel)data->state.resolver, socks, bitmask = ares_getsock((ares_channel)data->state.async.resolver, socks,
ARES_GETSOCK_MAXNUM); ARES_GETSOCK_MAXNUM);
for(i = 0; i < ARES_GETSOCK_MAXNUM; i++) { for(i = 0; i < ARES_GETSOCK_MAXNUM; i++) {
@ -324,12 +323,12 @@ static int waitperform(struct connectdata *conn, timediff_t timeout_ms)
if(!nfds) if(!nfds)
/* Call ares_process() unconditonally here, even if we simply timed out /* Call ares_process() unconditonally here, even if we simply timed out
above, as otherwise the ares name resolve won't timeout! */ above, as otherwise the ares name resolve won't timeout! */
ares_process_fd((ares_channel)data->state.resolver, ARES_SOCKET_BAD, ares_process_fd((ares_channel)data->state.async.resolver, ARES_SOCKET_BAD,
ARES_SOCKET_BAD); ARES_SOCKET_BAD);
else { else {
/* move through the descriptors and ask for processing on them */ /* 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, ares_process_fd((ares_channel)data->state.async.resolver,
(pfd[i].revents & (POLLRDNORM|POLLIN))? (pfd[i].revents & (POLLRDNORM|POLLIN))?
pfd[i].fd:ARES_SOCKET_BAD, pfd[i].fd:ARES_SOCKET_BAD,
(pfd[i].revents & (POLLWRNORM|POLLOUT))? (pfd[i].revents & (POLLWRNORM|POLLOUT))?
@ -345,17 +344,16 @@ static int waitperform(struct connectdata *conn, timediff_t timeout_ms)
* *
* Returns normal CURLcode errors. * Returns normal CURLcode errors.
*/ */
CURLcode Curl_resolver_is_resolved(struct connectdata *conn, CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
struct Curl_dns_entry **dns) struct Curl_dns_entry **dns)
{ {
struct Curl_easy *data = conn->data; struct thread_data *res = data->state.async.tdata;
struct thread_data *res = conn->async.tdata;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
DEBUGASSERT(dns); DEBUGASSERT(dns);
*dns = NULL; *dns = NULL;
waitperform(conn, 0); waitperform(data, 0);
/* Now that we've checked for any last minute results above, see if there are /* Now that we've checked for any last minute results above, see if there are
any responses still pending when the EXPIRE_HAPPY_EYEBALLS_DNS timer any responses still pending when the EXPIRE_HAPPY_EYEBALLS_DNS timer
@ -376,26 +374,27 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
ARES_ECANCELLED synchronously for all pending responses. This will ARES_ECANCELLED synchronously for all pending responses. This will
leave us with res->num_pending == 0, which is perfect for the next leave us with res->num_pending == 0, which is perfect for the next
block. */ block. */
ares_cancel((ares_channel)data->state.resolver); ares_cancel((ares_channel)data->state.async.resolver);
DEBUGASSERT(res->num_pending == 0); DEBUGASSERT(res->num_pending == 0);
} }
if(res && !res->num_pending) { if(res && !res->num_pending) {
(void)Curl_addrinfo_callback(conn, res->last_status, res->temp_ai); (void)Curl_addrinfo_callback(data, res->last_status, res->temp_ai);
/* temp_ai ownership is moved to the connection, so we need not free-up /* temp_ai ownership is moved to the connection, so we need not free-up
them */ them */
res->temp_ai = NULL; res->temp_ai = NULL;
if(!conn->async.dns) { if(!data->state.async.dns) {
failf(data, "Could not resolve: %s (%s)", failf(data, "Could not resolve: %s (%s)",
conn->async.hostname, ares_strerror(conn->async.status)); data->state.async.hostname,
result = conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY: ares_strerror(data->state.async.status));
result = data->conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
CURLE_COULDNT_RESOLVE_HOST; CURLE_COULDNT_RESOLVE_HOST;
} }
else else
*dns = conn->async.dns; *dns = data->state.async.dns;
destroy_async_data(&conn->async); destroy_async_data(&data->state.async);
} }
return result; return result;
@ -412,11 +411,10 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
* Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved,
* CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors. * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
*/ */
CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
struct Curl_dns_entry **entry) struct Curl_dns_entry **entry)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
timediff_t timeout; timediff_t timeout;
struct curltime now = Curl_now(); struct curltime now = Curl_now();
@ -426,7 +424,7 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
timeout = Curl_timeleft(data, &now, TRUE); timeout = Curl_timeleft(data, &now, TRUE);
if(timeout < 0) { if(timeout < 0) {
/* already expired! */ /* already expired! */
connclose(conn, "Timed out before name resolve started"); connclose(data->conn, "Timed out before name resolve started");
return CURLE_OPERATION_TIMEDOUT; return CURLE_OPERATION_TIMEDOUT;
} }
if(!timeout) if(!timeout)
@ -447,7 +445,7 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
store.tv_sec = itimeout/1000; store.tv_sec = itimeout/1000;
store.tv_usec = (itimeout%1000)*1000; store.tv_usec = (itimeout%1000)*1000;
tvp = ares_timeout((ares_channel)data->state.resolver, &store, &tv); tvp = ares_timeout((ares_channel)data->state.async.resolver, &store, &tv);
/* use the timeout period ares returned to us above if less than one /* 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 second is left, otherwise just use 1000ms to make sure the progress
@ -457,10 +455,10 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
else else
timeout_ms = 1000; timeout_ms = 1000;
waitperform(conn, timeout_ms); waitperform(data, timeout_ms);
result = Curl_resolver_is_resolved(conn, entry); result = Curl_resolver_is_resolved(data, entry);
if(result || conn->async.done) if(result || data->state.async.done)
break; break;
if(Curl_pgrsUpdate(data)) if(Curl_pgrsUpdate(data))
@ -481,17 +479,17 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
} }
if(result) if(result)
/* failure, so we cancel the ares operation */ /* failure, so we cancel the ares operation */
ares_cancel((ares_channel)data->state.resolver); ares_cancel((ares_channel)data->state.async.resolver);
/* Operation complete, if the lookup was successful we now have the entry /* Operation complete, if the lookup was successful we now have the entry
in the cache. */ in the cache. */
if(entry) if(entry)
*entry = conn->async.dns; *entry = data->state.async.dns;
if(result) if(result)
/* close the connection, since we can't return failure here without /* close the connection, since we can't return failure here without
cleaning up this connection properly. */ cleaning up this connection properly. */
connclose(conn, "c-ares resolve failed"); connclose(data->conn, "c-ares resolve failed");
return result; return result;
} }
@ -525,7 +523,7 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */
#endif #endif
struct hostent *hostent) struct hostent *hostent)
{ {
struct connectdata *conn = (struct connectdata *)arg; struct Curl_easy *data = (struct Curl_easy *)arg;
struct thread_data *res; struct thread_data *res;
#ifdef HAVE_CARES_CALLBACK_TIMEOUTS #ifdef HAVE_CARES_CALLBACK_TIMEOUTS
@ -537,12 +535,12 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */
be valid so only defer it when we know the 'status' says its fine! */ be valid so only defer it when we know the 'status' says its fine! */
return; return;
res = conn->async.tdata; res = data->state.async.tdata;
if(res) { if(res) {
res->num_pending--; res->num_pending--;
if(CURL_ASYNC_SUCCESS == status) { if(CURL_ASYNC_SUCCESS == status) {
struct Curl_addrinfo *ai = Curl_he2ai(hostent, conn->async.port); struct Curl_addrinfo *ai = Curl_he2ai(hostent, data->state.async.port);
if(ai) { if(ai) {
compound_results(res, ai); compound_results(res, ai);
} }
@ -607,8 +605,8 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */
c-ares retry cycle each request is. c-ares retry cycle each request is.
*/ */
res->happy_eyeballs_dns_time = Curl_now(); res->happy_eyeballs_dns_time = Curl_now();
Curl_expire( Curl_expire(data, HAPPY_EYEBALLS_DNS_TIMEOUT,
conn->data, HAPPY_EYEBALLS_DNS_TIMEOUT, EXPIRE_HAPPY_EYEBALLS_DNS); EXPIRE_HAPPY_EYEBALLS_DNS);
} }
} }
} }
@ -621,19 +619,18 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */
* memory we need to free after use. That memory *MUST* be freed with * memory we need to free after use. That memory *MUST* be freed with
* Curl_freeaddrinfo(), nothing else. * Curl_freeaddrinfo(), nothing else.
*/ */
struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
const char *hostname, const char *hostname,
int port, int port,
int *waitp) int *waitp)
{ {
char *bufp; char *bufp;
struct Curl_easy *data = conn->data;
int family = PF_INET; int family = PF_INET;
*waitp = 0; /* default to synchronous response */ *waitp = 0; /* default to synchronous response */
#ifdef ENABLE_IPV6 #ifdef ENABLE_IPV6
switch(conn->ip_version) { switch(data->set.ipver) {
default: default:
#if ARES_VERSION >= 0x010601 #if ARES_VERSION >= 0x010601
family = PF_UNSPEC; /* supported by c-ares since 1.6.1, so for older family = PF_UNSPEC; /* supported by c-ares since 1.6.1, so for older
@ -653,19 +650,19 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
bufp = strdup(hostname); bufp = strdup(hostname);
if(bufp) { if(bufp) {
struct thread_data *res = NULL; struct thread_data *res = NULL;
free(conn->async.hostname); free(data->state.async.hostname);
conn->async.hostname = bufp; data->state.async.hostname = bufp;
conn->async.port = port; data->state.async.port = port;
conn->async.done = FALSE; /* not done */ data->state.async.done = FALSE; /* not done */
conn->async.status = 0; /* clear */ data->state.async.status = 0; /* clear */
conn->async.dns = NULL; /* clear */ data->state.async.dns = NULL; /* clear */
res = calloc(sizeof(struct thread_data), 1); res = calloc(sizeof(struct thread_data), 1);
if(!res) { if(!res) {
free(conn->async.hostname); free(data->state.async.hostname);
conn->async.hostname = NULL; data->state.async.hostname = NULL;
return NULL; return NULL;
} }
conn->async.tdata = res; data->state.async.tdata = res;
/* initial status - failed */ /* initial status - failed */
res->last_status = ARES_ENOTFOUND; res->last_status = ARES_ENOTFOUND;
@ -675,17 +672,17 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
res->num_pending = 2; res->num_pending = 2;
/* areschannel is already setup in the Curl_open() function */ /* areschannel is already setup in the Curl_open() function */
ares_gethostbyname((ares_channel)data->state.resolver, hostname, ares_gethostbyname((ares_channel)data->state.async.resolver, hostname,
PF_INET, query_completed_cb, conn); PF_INET, query_completed_cb, data);
ares_gethostbyname((ares_channel)data->state.resolver, hostname, ares_gethostbyname((ares_channel)data->state.async.resolver, hostname,
PF_INET6, query_completed_cb, conn); PF_INET6, query_completed_cb, data);
} }
else { else {
res->num_pending = 1; res->num_pending = 1;
/* areschannel is already setup in the Curl_open() function */ /* areschannel is already setup in the Curl_open() function */
ares_gethostbyname((ares_channel)data->state.resolver, hostname, ares_gethostbyname((ares_channel)data->state.async.resolver, hostname,
PF_INET, query_completed_cb, conn); PF_INET, query_completed_cb, data);
} }
} }
else else
@ -694,8 +691,9 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
res->num_pending = 1; res->num_pending = 1;
/* areschannel is already setup in the Curl_open() function */ /* areschannel is already setup in the Curl_open() function */
ares_gethostbyname((ares_channel)data->state.resolver, hostname, family, ares_gethostbyname((ares_channel)data->state.async.resolver,
query_completed_cb, conn); hostname, family,
query_completed_cb, data);
} }
*waitp = 1; /* expect asynchronous response */ *waitp = 1; /* expect asynchronous response */
@ -720,9 +718,10 @@ CURLcode Curl_set_dns_servers(struct Curl_easy *data,
#if (ARES_VERSION >= 0x010704) #if (ARES_VERSION >= 0x010704)
#if (ARES_VERSION >= 0x010b00) #if (ARES_VERSION >= 0x010b00)
ares_result = ares_set_servers_ports_csv(data->state.resolver, servers); ares_result = ares_set_servers_ports_csv(data->state.async.resolver,
servers);
#else #else
ares_result = ares_set_servers_csv(data->state.resolver, servers); ares_result = ares_set_servers_csv(data->state.async.resolver, servers);
#endif #endif
switch(ares_result) { switch(ares_result) {
case ARES_SUCCESS: case ARES_SUCCESS:
@ -752,7 +751,7 @@ CURLcode Curl_set_dns_interface(struct Curl_easy *data,
if(!interf) if(!interf)
interf = ""; interf = "";
ares_set_local_dev((ares_channel)data->state.resolver, interf); ares_set_local_dev((ares_channel)data->state.async.resolver, interf);
return CURLE_OK; return CURLE_OK;
#else /* c-ares version too old! */ #else /* c-ares version too old! */
@ -777,7 +776,8 @@ CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data,
} }
} }
ares_set_local_ip4((ares_channel)data->state.resolver, ntohl(a4.s_addr)); ares_set_local_ip4((ares_channel)data->state.async.resolver,
ntohl(a4.s_addr));
return CURLE_OK; return CURLE_OK;
#else /* c-ares version too old! */ #else /* c-ares version too old! */
@ -803,7 +803,7 @@ CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data,
} }
} }
ares_set_local_ip6((ares_channel)data->state.resolver, a6); ares_set_local_ip6((ares_channel)data->state.async.resolver, a6);
return CURLE_OK; return CURLE_OK;
#else /* c-ares version too old! */ #else /* c-ares version too old! */

View File

@ -145,13 +145,13 @@ static void destroy_async_data(struct Curl_async *);
/* /*
* Cancel all possibly still on-going resolves for this connection. * Cancel all possibly still on-going resolves for this connection.
*/ */
void Curl_resolver_cancel(struct connectdata *conn) void Curl_resolver_cancel(struct Curl_easy *data)
{ {
destroy_async_data(&conn->async); destroy_async_data(&data->state.async);
} }
/* This function is used to init a threaded resolve */ /* This function is used to init a threaded resolve */
static bool init_resolve_thread(struct connectdata *conn, static bool init_resolve_thread(struct Curl_easy *data,
const char *hostname, int port, const char *hostname, int port,
const struct addrinfo *hints); const struct addrinfo *hints);
@ -164,7 +164,7 @@ struct thread_sync_data {
char *hostname; /* hostname to resolve, Curl_async.hostname char *hostname; /* hostname to resolve, Curl_async.hostname
duplicate */ duplicate */
#ifdef USE_SOCKETPAIR #ifdef USE_SOCKETPAIR
struct connectdata *conn; struct Curl_easy *data;
curl_socket_t sock_pair[2]; /* socket pair */ curl_socket_t sock_pair[2]; /* socket pair */
#endif #endif
int sock_error; int sock_error;
@ -182,9 +182,9 @@ struct thread_data {
struct thread_sync_data tsd; struct thread_sync_data tsd;
}; };
static struct thread_sync_data *conn_thread_sync_data(struct connectdata *conn) static struct thread_sync_data *conn_thread_sync_data(struct Curl_easy *data)
{ {
return &(conn->async.tdata->tsd); return &(data->state.async.tdata->tsd);
} }
/* Destroy resolver thread synchronization data */ /* Destroy resolver thread synchronization data */
@ -268,12 +268,12 @@ int init_thread_sync_data(struct thread_data *td,
return 0; return 0;
} }
static int getaddrinfo_complete(struct connectdata *conn) static int getaddrinfo_complete(struct Curl_easy *data)
{ {
struct thread_sync_data *tsd = conn_thread_sync_data(conn); struct thread_sync_data *tsd = conn_thread_sync_data(data);
int rc; int rc;
rc = Curl_addrinfo_callback(conn, tsd->sock_error, tsd->res); rc = Curl_addrinfo_callback(data, tsd->sock_error, tsd->res);
/* The tsd->res structure has been copied to async.dns and perhaps the DNS /* The tsd->res structure has been copied to async.dns and perhaps the DNS
cache. Set our copy to NULL so destroy_thread_sync_data doesn't free it. cache. Set our copy to NULL so destroy_thread_sync_data doesn't free it.
*/ */
@ -384,7 +384,7 @@ static void destroy_async_data(struct Curl_async *async)
int done; int done;
#ifdef USE_SOCKETPAIR #ifdef USE_SOCKETPAIR
curl_socket_t sock_rd = td->tsd.sock_pair[0]; curl_socket_t sock_rd = td->tsd.sock_pair[0];
struct connectdata *conn = td->tsd.conn; struct Curl_easy *data = td->tsd.data;
#endif #endif
/* /*
@ -412,8 +412,7 @@ static void destroy_async_data(struct Curl_async *async)
* ensure CURLMOPT_SOCKETFUNCTION fires CURL_POLL_REMOVE * ensure CURLMOPT_SOCKETFUNCTION fires CURL_POLL_REMOVE
* before the FD is invalidated to avoid EBADF on EPOLL_CTL_DEL * before the FD is invalidated to avoid EBADF on EPOLL_CTL_DEL
*/ */
if(conn) Curl_multi_closed(data, sock_rd);
Curl_multi_closed(conn->data, sock_rd);
sclose(sock_rd); sclose(sock_rd);
#endif #endif
} }
@ -429,32 +428,33 @@ static void destroy_async_data(struct Curl_async *async)
* *
* Returns FALSE in case of failure, otherwise TRUE. * Returns FALSE in case of failure, otherwise TRUE.
*/ */
static bool init_resolve_thread(struct connectdata *conn, static bool init_resolve_thread(struct Curl_easy *data,
const char *hostname, int port, const char *hostname, int port,
const struct addrinfo *hints) const struct addrinfo *hints)
{ {
struct thread_data *td = calloc(1, sizeof(struct thread_data)); struct thread_data *td = calloc(1, sizeof(struct thread_data));
int err = ENOMEM; int err = ENOMEM;
struct Curl_async *asp = &data->state.async;
conn->async.tdata = td; data->state.async.tdata = td;
if(!td) if(!td)
goto errno_exit; goto errno_exit;
conn->async.port = port; asp->port = port;
conn->async.done = FALSE; asp->done = FALSE;
conn->async.status = 0; asp->status = 0;
conn->async.dns = NULL; asp->dns = NULL;
td->thread_hnd = curl_thread_t_null; td->thread_hnd = curl_thread_t_null;
if(!init_thread_sync_data(td, hostname, port, hints)) { if(!init_thread_sync_data(td, hostname, port, hints)) {
conn->async.tdata = NULL; asp->tdata = NULL;
free(td); free(td);
goto errno_exit; goto errno_exit;
} }
free(conn->async.hostname); free(asp->hostname);
conn->async.hostname = strdup(hostname); asp->hostname = strdup(hostname);
if(!conn->async.hostname) if(!asp->hostname)
goto err_exit; goto err_exit;
/* The thread will set this to 1 when complete. */ /* The thread will set this to 1 when complete. */
@ -476,7 +476,7 @@ static bool init_resolve_thread(struct connectdata *conn,
return TRUE; return TRUE;
err_exit: err_exit:
destroy_async_data(&conn->async); destroy_async_data(asp);
errno_exit: errno_exit:
errno = err; errno = err;
@ -488,12 +488,13 @@ static bool init_resolve_thread(struct connectdata *conn,
* error * error
*/ */
static CURLcode resolver_error(struct connectdata *conn) static CURLcode resolver_error(struct Curl_easy *data)
{ {
const char *host_or_proxy; const char *host_or_proxy;
CURLcode result; CURLcode result;
#ifndef CURL_DISABLE_PROXY #ifndef CURL_DISABLE_PROXY
struct connectdata *conn = data->conn;
if(conn->bits.httpproxy) { if(conn->bits.httpproxy) {
host_or_proxy = "proxy"; host_or_proxy = "proxy";
result = CURLE_COULDNT_RESOLVE_PROXY; result = CURLE_COULDNT_RESOLVE_PROXY;
@ -505,8 +506,8 @@ static CURLcode resolver_error(struct connectdata *conn)
result = CURLE_COULDNT_RESOLVE_HOST; result = CURLE_COULDNT_RESOLVE_HOST;
} }
failf(conn->data, "Could not resolve %s: %s", host_or_proxy, failf(data, "Could not resolve %s: %s", host_or_proxy,
conn->async.hostname); data->state.async.hostname);
return result; return result;
} }
@ -514,37 +515,39 @@ static CURLcode resolver_error(struct connectdata *conn)
/* /*
* 'entry' may be NULL and then no data is returned * 'entry' may be NULL and then no data is returned
*/ */
static CURLcode thread_wait_resolv(struct connectdata *conn, static CURLcode thread_wait_resolv(struct Curl_easy *data,
struct Curl_dns_entry **entry, struct Curl_dns_entry **entry,
bool report) bool report)
{ {
struct thread_data *td = conn->async.tdata; struct thread_data *td;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
DEBUGASSERT(conn && td); DEBUGASSERT(data);
td = data->state.async.tdata;
DEBUGASSERT(td);
DEBUGASSERT(td->thread_hnd != curl_thread_t_null); DEBUGASSERT(td->thread_hnd != curl_thread_t_null);
/* wait for the thread to resolve the name */ /* wait for the thread to resolve the name */
if(Curl_thread_join(&td->thread_hnd)) { if(Curl_thread_join(&td->thread_hnd)) {
if(entry) if(entry)
result = getaddrinfo_complete(conn); result = getaddrinfo_complete(data);
} }
else else
DEBUGASSERT(0); DEBUGASSERT(0);
conn->async.done = TRUE; data->state.async.done = TRUE;
if(entry) if(entry)
*entry = conn->async.dns; *entry = data->state.async.dns;
if(!conn->async.dns && report) if(!data->state.async.dns && report)
/* a name was not resolved, report error */ /* a name was not resolved, report error */
result = resolver_error(conn); result = resolver_error(data);
destroy_async_data(&conn->async); destroy_async_data(&data->state.async);
if(!conn->async.dns && report) if(!data->state.async.dns && report)
connclose(conn, "asynch resolve failed"); connclose(data->conn, "asynch resolve failed");
return result; return result;
} }
@ -554,17 +557,17 @@ static CURLcode thread_wait_resolv(struct connectdata *conn,
* Until we gain a way to signal the resolver threads to stop early, we must * Until we gain a way to signal the resolver threads to stop early, we must
* simply wait for them and ignore their results. * simply wait for them and ignore their results.
*/ */
void Curl_resolver_kill(struct connectdata *conn) void Curl_resolver_kill(struct Curl_easy *data)
{ {
struct thread_data *td = conn->async.tdata; struct thread_data *td = data->state.async.tdata;
/* If we're still resolving, we must wait for the threads to fully clean up, /* If we're still resolving, we must wait for the threads to fully clean up,
unfortunately. Otherwise, we can simply cancel to clean up any resolver unfortunately. Otherwise, we can simply cancel to clean up any resolver
data. */ data. */
if(td && td->thread_hnd != curl_thread_t_null) if(td && td->thread_hnd != curl_thread_t_null)
(void)thread_wait_resolv(conn, NULL, FALSE); (void)thread_wait_resolv(data, NULL, FALSE);
else else
Curl_resolver_cancel(conn); Curl_resolver_cancel(data);
} }
/* /*
@ -580,10 +583,10 @@ void Curl_resolver_kill(struct connectdata *conn)
* *
* This is the version for resolves-in-a-thread. * This is the version for resolves-in-a-thread.
*/ */
CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
struct Curl_dns_entry **entry) struct Curl_dns_entry **entry)
{ {
return thread_wait_resolv(conn, entry, TRUE); return thread_wait_resolv(data, entry, TRUE);
} }
/* /*
@ -591,11 +594,10 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
* name resolve request has completed. It should also make sure to time-out if * name resolve request has completed. It should also make sure to time-out if
* the operation seems to take too long. * the operation seems to take too long.
*/ */
CURLcode Curl_resolver_is_resolved(struct connectdata *conn, CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
struct Curl_dns_entry **entry) struct Curl_dns_entry **entry)
{ {
struct Curl_easy *data = conn->data; struct thread_data *td = data->state.async.tdata;
struct thread_data *td = conn->async.tdata;
int done = 0; int done = 0;
DEBUGASSERT(entry); DEBUGASSERT(entry);
@ -611,15 +613,15 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
Curl_mutex_release(td->tsd.mtx); Curl_mutex_release(td->tsd.mtx);
if(done) { if(done) {
getaddrinfo_complete(conn); getaddrinfo_complete(data);
if(!conn->async.dns) { if(!data->state.async.dns) {
CURLcode result = resolver_error(conn); CURLcode result = resolver_error(data);
destroy_async_data(&conn->async); destroy_async_data(&data->state.async);
return result; return result;
} }
destroy_async_data(&conn->async); destroy_async_data(&data->state.async);
*entry = conn->async.dns; *entry = data->state.async.dns;
} }
else { else {
/* poll for name lookup done with exponential backoff up to 250ms */ /* poll for name lookup done with exponential backoff up to 250ms */
@ -640,22 +642,20 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
td->poll_interval = 250; td->poll_interval = 250;
td->interval_end = elapsed + td->poll_interval; td->interval_end = elapsed + td->poll_interval;
Curl_expire(conn->data, td->poll_interval, EXPIRE_ASYNC_NAME); Curl_expire(data, td->poll_interval, EXPIRE_ASYNC_NAME);
} }
return CURLE_OK; return CURLE_OK;
} }
int Curl_resolver_getsock(struct connectdata *conn, int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *socks)
curl_socket_t *socks)
{ {
int ret_val = 0; int ret_val = 0;
timediff_t milli; timediff_t milli;
timediff_t ms; timediff_t ms;
struct Curl_easy *data = conn->data; struct resdata *reslv = (struct resdata *)data->state.async.resolver;
struct resdata *reslv = (struct resdata *)data->state.resolver;
#ifdef USE_SOCKETPAIR #ifdef USE_SOCKETPAIR
struct thread_data *td = conn->async.tdata; struct thread_data *td = data->state.async.tdata;
#else #else
(void)socks; (void)socks;
#endif #endif
@ -664,8 +664,7 @@ int Curl_resolver_getsock(struct connectdata *conn,
if(td) { if(td) {
/* return read fd to client for polling the DNS resolution status */ /* return read fd to client for polling the DNS resolution status */
socks[0] = td->tsd.sock_pair[0]; socks[0] = td->tsd.sock_pair[0];
DEBUGASSERT(td->tsd.conn == conn || !td->tsd.conn); td->tsd.data = data;
td->tsd.conn = conn;
ret_val = GETSOCK_READSOCK(0); ret_val = GETSOCK_READSOCK(0);
} }
else { else {
@ -692,12 +691,11 @@ int Curl_resolver_getsock(struct connectdata *conn,
/* /*
* Curl_getaddrinfo() - for platforms without getaddrinfo * Curl_getaddrinfo() - for platforms without getaddrinfo
*/ */
struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
const char *hostname, const char *hostname,
int port, int port,
int *waitp) int *waitp)
{ {
struct Curl_easy *data = conn->data;
struct resdata *reslv = (struct resdata *)data->state.resolver; struct resdata *reslv = (struct resdata *)data->state.resolver;
*waitp = 0; /* default to synchronous response */ *waitp = 0; /* default to synchronous response */
@ -705,7 +703,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
reslv->start = Curl_now(); reslv->start = Curl_now();
/* fire up a new resolver thread! */ /* fire up a new resolver thread! */
if(init_resolve_thread(conn, hostname, port, NULL)) { if(init_resolve_thread(data, hostname, port, NULL)) {
*waitp = 1; /* expect asynchronous response */ *waitp = 1; /* expect asynchronous response */
return NULL; return NULL;
} }
@ -720,15 +718,14 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
/* /*
* Curl_resolver_getaddrinfo() - for getaddrinfo * Curl_resolver_getaddrinfo() - for getaddrinfo
*/ */
struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
const char *hostname, const char *hostname,
int port, int port,
int *waitp) int *waitp)
{ {
struct addrinfo hints; struct addrinfo hints;
int pf = PF_INET; int pf = PF_INET;
struct Curl_easy *data = conn->data; struct resdata *reslv = (struct resdata *)data->state.async.resolver;
struct resdata *reslv = (struct resdata *)data->state.resolver;
*waitp = 0; /* default to synchronous response */ *waitp = 0; /* default to synchronous response */
@ -736,7 +733,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
/* /*
* Check if a limited name resolve has been requested. * Check if a limited name resolve has been requested.
*/ */
switch(conn->ip_version) { switch(data->set.ipver) {
case CURL_IPRESOLVE_V4: case CURL_IPRESOLVE_V4:
pf = PF_INET; pf = PF_INET;
break; break;
@ -755,12 +752,12 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
memset(&hints, 0, sizeof(hints)); memset(&hints, 0, sizeof(hints));
hints.ai_family = pf; hints.ai_family = pf;
hints.ai_socktype = (conn->transport == TRNSPRT_TCP)? hints.ai_socktype = (data->conn->transport == TRNSPRT_TCP)?
SOCK_STREAM : SOCK_DGRAM; SOCK_STREAM : SOCK_DGRAM;
reslv->start = Curl_now(); reslv->start = Curl_now();
/* fire up a new resolver thread! */ /* fire up a new resolver thread! */
if(init_resolve_thread(conn, hostname, port, &hints)) { if(init_resolve_thread(data, hostname, port, &hints)) {
*waitp = 1; /* expect asynchronous response */ *waitp = 1; /* expect asynchronous response */
return NULL; return NULL;
} }

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -91,7 +91,7 @@ CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to,
* *
* It is safe to call this when conn is in any state. * It is safe to call this when conn is in any state.
*/ */
void Curl_resolver_cancel(struct connectdata *conn); void Curl_resolver_cancel(struct Curl_easy *data);
/* /*
* Curl_resolver_kill(). * Curl_resolver_kill().
@ -104,7 +104,7 @@ void Curl_resolver_cancel(struct connectdata *conn);
* *
* It is safe to call this when conn is in any state. * It is safe to call this when conn is in any state.
*/ */
void Curl_resolver_kill(struct connectdata *conn); void Curl_resolver_kill(struct Curl_easy *data);
/* Curl_resolver_getsock() /* Curl_resolver_getsock()
* *
@ -114,7 +114,7 @@ void Curl_resolver_kill(struct connectdata *conn);
* return bitmask indicating what file descriptors (referring to array indexes * return bitmask indicating what file descriptors (referring to array indexes
* in the 'sock' array) to wait for, read/write. * in the 'sock' array) to wait for, read/write.
*/ */
int Curl_resolver_getsock(struct connectdata *conn, curl_socket_t *sock); int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *sock);
/* /*
* Curl_resolver_is_resolved() * Curl_resolver_is_resolved()
@ -125,7 +125,7 @@ int Curl_resolver_getsock(struct connectdata *conn, curl_socket_t *sock);
* *
* Returns normal CURLcode errors. * Returns normal CURLcode errors.
*/ */
CURLcode Curl_resolver_is_resolved(struct connectdata *conn, CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
struct Curl_dns_entry **dns); struct Curl_dns_entry **dns);
/* /*
@ -139,7 +139,7 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
* Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved,
* CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors. * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
*/ */
CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
struct Curl_dns_entry **dnsentry); struct Curl_dns_entry **dnsentry);
/* /*
@ -153,7 +153,7 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
* Each resolver backend must of course make sure to return data in the * Each resolver backend must of course make sure to return data in the
* correct format to comply with this. * correct format to comply with this.
*/ */
struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
const char *hostname, const char *hostname,
int port, int port,
int *waitp); int *waitp);

View File

@ -358,9 +358,9 @@ static CURLcode bindlocal(struct Curl_easy *data,
conn->ip_version = CURL_IPRESOLVE_V6; conn->ip_version = CURL_IPRESOLVE_V6;
#endif #endif
rc = Curl_resolv(conn, dev, 0, FALSE, &h); rc = Curl_resolv(data, dev, 0, FALSE, &h);
if(rc == CURLRESOLV_PENDING) if(rc == CURLRESOLV_PENDING)
(void)Curl_resolver_wait_resolv(conn, &h); (void)Curl_resolver_wait_resolv(data, &h);
conn->ip_version = ipver; conn->ip_version = ipver;
if(h) { if(h) {

View File

@ -379,21 +379,21 @@ static CURLcode dohprobe(struct Curl_easy *data,
* 'Curl_addrinfo *' with the address information. * 'Curl_addrinfo *' with the address information.
*/ */
struct Curl_addrinfo *Curl_doh(struct connectdata *conn, struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
const char *hostname, const char *hostname,
int port, int port,
int *waitp) int *waitp)
{ {
struct Curl_easy *data = conn->data;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
int slot; int slot;
struct dohdata *dohp; struct dohdata *dohp;
struct connectdata *conn = data->conn;
*waitp = TRUE; /* this never returns synchronously */ *waitp = TRUE; /* this never returns synchronously */
(void)conn;
(void)hostname; (void)hostname;
(void)port; (void)port;
DEBUGASSERT(!data->req.doh); DEBUGASSERT(!data->req.doh);
DEBUGASSERT(conn);
/* start clean, consider allocating this struct on demand */ /* start clean, consider allocating this struct on demand */
dohp = data->req.doh = calloc(sizeof(struct dohdata), 1); dohp = data->req.doh = calloc(sizeof(struct dohdata), 1);
@ -911,11 +911,10 @@ UNITTEST void de_cleanup(struct dohentry *d)
} }
} }
CURLcode Curl_doh_is_resolved(struct connectdata *conn, CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
struct Curl_dns_entry **dnsp) struct Curl_dns_entry **dnsp)
{ {
CURLcode result; CURLcode result;
struct Curl_easy *data = conn->data;
struct dohdata *dohp = data->req.doh; struct dohdata *dohp = data->req.doh;
*dnsp = NULL; /* defaults to no response */ *dnsp = NULL; /* defaults to no response */
if(!dohp) if(!dohp)
@ -923,8 +922,8 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
if(!dohp->probe[DOH_PROBE_SLOT_IPADDR_V4].easy && if(!dohp->probe[DOH_PROBE_SLOT_IPADDR_V4].easy &&
!dohp->probe[DOH_PROBE_SLOT_IPADDR_V6].easy) { !dohp->probe[DOH_PROBE_SLOT_IPADDR_V6].easy) {
failf(data, "Could not DOH-resolve: %s", conn->async.hostname); failf(data, "Could not DOH-resolve: %s", data->state.async.hostname);
return conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY: return data->conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
CURLE_COULDNT_RESOLVE_HOST; CURLE_COULDNT_RESOLVE_HOST;
} }
else if(!dohp->pending) { else if(!dohp->pending) {
@ -984,7 +983,7 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
Curl_freeaddrinfo(ai); Curl_freeaddrinfo(ai);
} }
else { else {
conn->async.dns = dns; data->state.async.dns = dns;
*dnsp = dns; *dnsp = dns;
result = CURLE_OK; /* address resolution OK */ result = CURLE_OK; /* address resolution OK */
} }

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2018 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2018 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -32,12 +32,12 @@
* and returns a 'Curl_addrinfo *' with the address information. * and returns a 'Curl_addrinfo *' with the address information.
*/ */
struct Curl_addrinfo *Curl_doh(struct connectdata *conn, struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
const char *hostname, const char *hostname,
int port, int port,
int *waitp); int *waitp);
CURLcode Curl_doh_is_resolved(struct connectdata *conn, CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
struct Curl_dns_entry **dns); struct Curl_dns_entry **dns);
int Curl_doh_getsock(struct connectdata *conn, curl_socket_t *socks); int Curl_doh_getsock(struct connectdata *conn, curl_socket_t *socks);

View File

@ -908,8 +908,8 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
#endif #endif
/* Clone the resolver handle, if present, for the new handle */ /* Clone the resolver handle, if present, for the new handle */
if(Curl_resolver_duphandle(outcurl, if(Curl_resolver_duphandle(outcurl,
&outcurl->state.resolver, &outcurl->state.async.resolver,
data->state.resolver)) data->state.async.resolver))
goto fail; goto fail;
#ifdef USE_ARES #ifdef USE_ARES

View File

@ -1079,9 +1079,9 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
} }
/* resolv ip/host to ip */ /* resolv ip/host to ip */
rc = Curl_resolv(conn, host, 0, FALSE, &h); rc = Curl_resolv(data, host, 0, FALSE, &h);
if(rc == CURLRESOLV_PENDING) if(rc == CURLRESOLV_PENDING)
(void)Curl_resolver_wait_resolv(conn, &h); (void)Curl_resolver_wait_resolv(data, &h);
if(h) { if(h) {
res = h->addr; res = h->addr;
/* when we return from this function, we can forget about this entry /* when we return from this function, we can forget about this entry
@ -1945,11 +1945,11 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data,
*/ */
const char * const host_name = conn->bits.socksproxy ? const char * const host_name = conn->bits.socksproxy ?
conn->socks_proxy.host.name : conn->http_proxy.host.name; conn->socks_proxy.host.name : conn->http_proxy.host.name;
rc = Curl_resolv(conn, host_name, (int)conn->port, FALSE, &addr); rc = Curl_resolv(data, host_name, (int)conn->port, FALSE, &addr);
if(rc == CURLRESOLV_PENDING) if(rc == CURLRESOLV_PENDING)
/* BLOCKING, ignores the return code but 'addr' will be NULL in /* BLOCKING, ignores the return code but 'addr' will be NULL in
case of failure */ case of failure */
(void)Curl_resolver_wait_resolv(conn, &addr); (void)Curl_resolver_wait_resolv(data, &addr);
connectport = connectport =
(unsigned short)conn->port; /* we connect to the proxy's port */ (unsigned short)conn->port; /* we connect to the proxy's port */
@ -1974,10 +1974,10 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data,
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
rc = Curl_resolv(conn, ftpc->newhost, ftpc->newport, FALSE, &addr); rc = Curl_resolv(data, ftpc->newhost, ftpc->newport, FALSE, &addr);
if(rc == CURLRESOLV_PENDING) if(rc == CURLRESOLV_PENDING)
/* BLOCKING */ /* BLOCKING */
(void)Curl_resolver_wait_resolv(conn, &addr); (void)Curl_resolver_wait_resolv(data, &addr);
connectport = ftpc->newport; /* we connect to the remote port */ connectport = ftpc->newport; /* we connect to the remote port */

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -66,25 +66,23 @@
* *
* The storage operation locks and unlocks the DNS cache. * The storage operation locks and unlocks the DNS cache.
*/ */
CURLcode Curl_addrinfo_callback(struct connectdata *conn, CURLcode Curl_addrinfo_callback(struct Curl_easy *data,
int status, int status,
struct Curl_addrinfo *ai) struct Curl_addrinfo *ai)
{ {
struct Curl_dns_entry *dns = NULL; struct Curl_dns_entry *dns = NULL;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
conn->async.status = status; data->state.async.status = status;
if(CURL_ASYNC_SUCCESS == status) { if(CURL_ASYNC_SUCCESS == status) {
if(ai) { if(ai) {
struct Curl_easy *data = conn->data;
if(data->share) if(data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
dns = Curl_cache_addr(data, ai, dns = Curl_cache_addr(data, ai,
conn->async.hostname, data->state.async.hostname,
conn->async.port); data->state.async.port);
if(data->share) if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS); Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
@ -99,12 +97,12 @@ CURLcode Curl_addrinfo_callback(struct connectdata *conn,
} }
} }
conn->async.dns = dns; data->state.async.dns = dns;
/* Set async.done TRUE last in this function since it may be used multi- /* Set async.done TRUE last in this function since it may be used multi-
threaded and once this is TRUE the other thread may read fields from the threaded and once this is TRUE the other thread may read fields from the
async struct */ async struct */
conn->async.done = TRUE; data->state.async.done = TRUE;
/* IPv4: The input hostent struct will be freed by ares when we return from /* IPv4: The input hostent struct will be freed by ares when we return from
this function */ this function */
@ -117,12 +115,12 @@ CURLcode Curl_addrinfo_callback(struct connectdata *conn,
* name resolve layers (selected at build-time). They all take this same set * name resolve layers (selected at build-time). They all take this same set
* of arguments * of arguments
*/ */
struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
const char *hostname, const char *hostname,
int port, int port,
int *waitp) int *waitp)
{ {
return Curl_resolver_getaddrinfo(conn, hostname, port, waitp); return Curl_resolver_getaddrinfo(data, hostname, port, waitp);
} }
#endif /* CURLRES_ASYNCH */ #endif /* CURLRES_ASYNCH */

View File

@ -253,14 +253,12 @@ sigjmp_buf curl_jmpenv;
#endif #endif
/* lookup address, returns entry if found and not stale */ /* lookup address, returns entry if found and not stale */
static struct Curl_dns_entry * static struct Curl_dns_entry *fetch_addr(struct Curl_easy *data,
fetch_addr(struct connectdata *conn,
const char *hostname, const char *hostname,
int port) int port)
{ {
struct Curl_dns_entry *dns = NULL; struct Curl_dns_entry *dns = NULL;
size_t entry_len; size_t entry_len;
struct Curl_easy *data = conn->data;
char entry_id[MAX_HOSTCACHE_LEN]; char entry_id[MAX_HOSTCACHE_LEN];
/* Create an entry id, based upon the hostname and port */ /* Create an entry id, based upon the hostname and port */
@ -321,7 +319,7 @@ Curl_fetch_addr(struct connectdata *conn,
if(data->share) if(data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
dns = fetch_addr(conn, hostname, port); dns = fetch_addr(data, hostname, port);
if(dns) if(dns)
dns->inuse++; /* we use it! */ dns->inuse++; /* we use it! */
@ -480,16 +478,16 @@ Curl_cache_addr(struct Curl_easy *data,
* CURLRESOLV_PENDING (1) = waiting for response, no pointer * CURLRESOLV_PENDING (1) = waiting for response, no pointer
*/ */
enum resolve_t Curl_resolv(struct connectdata *conn, enum resolve_t Curl_resolv(struct Curl_easy *data,
const char *hostname, const char *hostname,
int port, int port,
bool allowDOH, bool allowDOH,
struct Curl_dns_entry **entry) struct Curl_dns_entry **entry)
{ {
struct Curl_dns_entry *dns = NULL; struct Curl_dns_entry *dns = NULL;
struct Curl_easy *data = conn->data;
CURLcode result; CURLcode result;
enum resolve_t rc = CURLRESOLV_ERROR; /* default to failure */ enum resolve_t rc = CURLRESOLV_ERROR; /* default to failure */
struct connectdata *conn = data->conn;
*entry = NULL; *entry = NULL;
conn->bits.doh = FALSE; /* default is not */ conn->bits.doh = FALSE; /* default is not */
@ -497,7 +495,7 @@ enum resolve_t Curl_resolv(struct connectdata *conn,
if(data->share) if(data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
dns = fetch_addr(conn, hostname, port); dns = fetch_addr(data, hostname, port);
if(dns) { if(dns) {
infof(data, "Hostname %s was found in DNS cache\n", hostname); infof(data, "Hostname %s was found in DNS cache\n", hostname);
@ -523,7 +521,7 @@ enum resolve_t Curl_resolv(struct connectdata *conn,
if(data->set.resolver_start) { if(data->set.resolver_start) {
int st; int st;
Curl_set_in_callback(data, true); Curl_set_in_callback(data, true);
st = data->set.resolver_start(data->state.resolver, NULL, st = data->set.resolver_start(data->state.async.resolver, NULL,
data->set.resolver_start_client); data->set.resolver_start_client);
Curl_set_in_callback(data, false); Curl_set_in_callback(data, false);
if(st) if(st)
@ -569,13 +567,13 @@ enum resolve_t Curl_resolv(struct connectdata *conn,
return CURLRESOLV_ERROR; return CURLRESOLV_ERROR;
if(allowDOH && data->set.doh && !ipnum) { if(allowDOH && data->set.doh && !ipnum) {
addr = Curl_doh(conn, hostname, port, &respwait); addr = Curl_doh(data, hostname, port, &respwait);
} }
else { else {
/* If Curl_getaddrinfo() returns NULL, 'respwait' might be set to a /* If Curl_getaddrinfo() returns NULL, 'respwait' might be set to a
non-zero value indicating that we need to wait for the response to non-zero value indicating that we need to wait for the response to
the resolve call */ the resolve call */
addr = Curl_getaddrinfo(conn, addr = Curl_getaddrinfo(data,
#ifdef DEBUGBUILD #ifdef DEBUGBUILD
(data->set.str[STRING_DEVICE] (data->set.str[STRING_DEVICE]
&& !strcmp(data->set.str[STRING_DEVICE], && !strcmp(data->set.str[STRING_DEVICE],
@ -589,7 +587,7 @@ enum resolve_t Curl_resolv(struct connectdata *conn,
/* the response to our resolve call will come asynchronously at /* the response to our resolve call will come asynchronously at
a later time, good or bad */ a later time, good or bad */
/* First, check that we haven't received the info by now */ /* First, check that we haven't received the info by now */
result = Curl_resolv_check(conn, &dns); result = Curl_resolv_check(data, &dns);
if(result) /* error detected */ if(result) /* error detected */
return CURLRESOLV_ERROR; return CURLRESOLV_ERROR;
if(dns) if(dns)
@ -658,7 +656,7 @@ RETSIGTYPE alarmfunc(int sig)
* CURLRESOLV_PENDING (1) = waiting for response, no pointer * CURLRESOLV_PENDING (1) = waiting for response, no pointer
*/ */
enum resolve_t Curl_resolv_timeout(struct connectdata *conn, enum resolve_t Curl_resolv_timeout(struct Curl_easy *data,
const char *hostname, const char *hostname,
int port, int port,
struct Curl_dns_entry **entry, struct Curl_dns_entry **entry,
@ -676,7 +674,6 @@ enum resolve_t Curl_resolv_timeout(struct connectdata *conn,
#endif /* HAVE_SIGACTION */ #endif /* HAVE_SIGACTION */
volatile long timeout; volatile long timeout;
volatile unsigned int prev_alarm = 0; volatile unsigned int prev_alarm = 0;
struct Curl_easy *data = conn->data;
#endif /* USE_ALARM_TIMEOUT */ #endif /* USE_ALARM_TIMEOUT */
enum resolve_t rc; enum resolve_t rc;
@ -695,7 +692,7 @@ enum resolve_t Curl_resolv_timeout(struct connectdata *conn,
if(!timeout) if(!timeout)
/* USE_ALARM_TIMEOUT defined, but no timeout actually requested */ /* USE_ALARM_TIMEOUT defined, but no timeout actually requested */
return Curl_resolv(conn, hostname, port, TRUE, entry); return Curl_resolv(data, hostname, port, TRUE, entry);
if(timeout < 1000) { if(timeout < 1000) {
/* The alarm() function only provides integer second resolution, so if /* The alarm() function only provides integer second resolution, so if
@ -748,7 +745,7 @@ enum resolve_t Curl_resolv_timeout(struct connectdata *conn,
#else #else
#ifndef CURLRES_ASYNCH #ifndef CURLRES_ASYNCH
if(timeoutms) if(timeoutms)
infof(conn->data, "timeout on name lookup is not supported\n"); infof(data, "timeout on name lookup is not supported\n");
#else #else
(void)timeoutms; /* timeoutms not used with an async resolver */ (void)timeoutms; /* timeoutms not used with an async resolver */
#endif #endif
@ -757,7 +754,7 @@ enum resolve_t Curl_resolv_timeout(struct connectdata *conn,
/* Perform the actual name resolution. This might be interrupted by an /* Perform the actual name resolution. This might be interrupted by an
* alarm if it takes too long. * alarm if it takes too long.
*/ */
rc = Curl_resolv(conn, hostname, port, TRUE, entry); rc = Curl_resolv(data, hostname, port, TRUE, entry);
#ifdef USE_ALARM_TIMEOUT #ifdef USE_ALARM_TIMEOUT
clean_up: clean_up:
@ -784,7 +781,7 @@ clean_up:
if(prev_alarm) { if(prev_alarm) {
/* there was an alarm() set before us, now put it back */ /* there was an alarm() set before us, now put it back */
timediff_t elapsed_secs = Curl_timediff(Curl_now(), timediff_t elapsed_secs = Curl_timediff(Curl_now(),
conn->created) / 1000; data->conn->created) / 1000;
/* the alarm period is counted in even number of seconds */ /* the alarm period is counted in even number of seconds */
unsigned long alarm_set = (unsigned long)(prev_alarm - elapsed_secs); unsigned long alarm_set = (unsigned long)(prev_alarm - elapsed_secs);
@ -1068,29 +1065,29 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
return CURLE_OK; return CURLE_OK;
} }
CURLcode Curl_resolv_check(struct connectdata *conn, CURLcode Curl_resolv_check(struct Curl_easy *data,
struct Curl_dns_entry **dns) struct Curl_dns_entry **dns)
{ {
#if defined(CURL_DISABLE_DOH) && !defined(CURLRES_ASYNCH) #if defined(CURL_DISABLE_DOH) && !defined(CURLRES_ASYNCH)
(void)dns; (void)dns;
#endif #endif
if(conn->bits.doh) if(data->conn->bits.doh)
return Curl_doh_is_resolved(conn, dns); return Curl_doh_is_resolved(data, dns);
return Curl_resolver_is_resolved(conn, dns); return Curl_resolver_is_resolved(data, dns);
} }
int Curl_resolv_getsock(struct connectdata *conn, int Curl_resolv_getsock(struct Curl_easy *data,
curl_socket_t *socks) curl_socket_t *socks)
{ {
#ifdef CURLRES_ASYNCH #ifdef CURLRES_ASYNCH
if(conn->bits.doh) if(data->conn->bits.doh)
/* nothing to wait for during DOH resolve, those handles have their own /* nothing to wait for during DOH resolve, those handles have their own
sockets */ sockets */
return GETSOCK_BLANK; return GETSOCK_BLANK;
return Curl_resolver_getsock(conn, socks); return Curl_resolver_getsock(data, socks);
#else #else
(void)conn; (void)data;
(void)socks; (void)socks;
return GETSOCK_BLANK; return GETSOCK_BLANK;
#endif #endif
@ -1101,21 +1098,19 @@ int Curl_resolv_getsock(struct connectdata *conn,
Note: this function disconnects and frees the conn data in case of Note: this function disconnects and frees the conn data in case of
resolve failure */ resolve failure */
CURLcode Curl_once_resolved(struct connectdata *conn, CURLcode Curl_once_resolved(struct Curl_easy *data, bool *protocol_done)
bool *protocol_done)
{ {
CURLcode result; CURLcode result;
struct connectdata *conn = data->conn;
if(conn->async.dns) { if(data->state.async.dns) {
conn->dns_entry = conn->async.dns; conn->dns_entry = data->state.async.dns;
conn->async.dns = NULL; data->state.async.dns = NULL;
} }
result = Curl_setup_conn(conn, protocol_done); result = Curl_setup_conn(conn, protocol_done);
if(result) { if(result) {
struct Curl_easy *data = conn->data;
DEBUGASSERT(data);
Curl_detach_connnection(data); Curl_detach_connnection(data);
Curl_conncache_remove_conn(data, conn, TRUE); Curl_conncache_remove_conn(data, conn, TRUE);
Curl_disconnect(data, conn, TRUE); Curl_disconnect(data, conn, TRUE);

View File

@ -85,12 +85,12 @@ enum resolve_t {
CURLRESOLV_RESOLVED = 0, CURLRESOLV_RESOLVED = 0,
CURLRESOLV_PENDING = 1 CURLRESOLV_PENDING = 1
}; };
enum resolve_t Curl_resolv(struct connectdata *conn, enum resolve_t Curl_resolv(struct Curl_easy *data,
const char *hostname, const char *hostname,
int port, int port,
bool allowDOH, bool allowDOH,
struct Curl_dns_entry **dnsentry); struct Curl_dns_entry **dnsentry);
enum resolve_t Curl_resolv_timeout(struct connectdata *conn, enum resolve_t Curl_resolv_timeout(struct Curl_easy *data,
const char *hostname, int port, const char *hostname, int port,
struct Curl_dns_entry **dnsentry, struct Curl_dns_entry **dnsentry,
timediff_t timeoutms); timediff_t timeoutms);
@ -117,7 +117,7 @@ bool Curl_ipvalid(struct Curl_easy *data, struct connectdata *conn);
* name resolve layers (selected at build-time). They all take this same set * name resolve layers (selected at build-time). They all take this same set
* of arguments * of arguments
*/ */
struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
const char *hostname, const char *hostname,
int port, int port,
int *waitp); int *waitp);
@ -148,7 +148,7 @@ int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa,
/* IPv4 threadsafe resolve function used for synch and asynch builds */ /* IPv4 threadsafe resolve function used for synch and asynch builds */
struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, int port); struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, int port);
CURLcode Curl_once_resolved(struct connectdata *conn, bool *protocol_connect); CURLcode Curl_once_resolved(struct Curl_easy *data, bool *protocol_connect);
/* /*
* Curl_addrinfo_callback() is used when we build with any asynch specialty. * Curl_addrinfo_callback() is used when we build with any asynch specialty.
@ -156,7 +156,7 @@ CURLcode Curl_once_resolved(struct connectdata *conn, bool *protocol_connect);
* status is CURL_ASYNC_SUCCESS. Twiddles fields in conn to indicate async * status is CURL_ASYNC_SUCCESS. Twiddles fields in conn to indicate async
* request completed whether successful or failed. * request completed whether successful or failed.
*/ */
CURLcode Curl_addrinfo_callback(struct connectdata *conn, CURLcode Curl_addrinfo_callback(struct Curl_easy *data,
int status, int status,
struct Curl_addrinfo *ai); struct Curl_addrinfo *ai);
@ -240,10 +240,9 @@ void Curl_hostcache_clean(struct Curl_easy *data, struct Curl_hash *hash);
* Populate the cache with specified entries from CURLOPT_RESOLVE. * Populate the cache with specified entries from CURLOPT_RESOLVE.
*/ */
CURLcode Curl_loadhostpairs(struct Curl_easy *data); CURLcode Curl_loadhostpairs(struct Curl_easy *data);
CURLcode Curl_resolv_check(struct Curl_easy *data,
CURLcode Curl_resolv_check(struct connectdata *conn,
struct Curl_dns_entry **dns); struct Curl_dns_entry **dns);
int Curl_resolv_getsock(struct connectdata *conn, int Curl_resolv_getsock(struct Curl_easy *data,
curl_socket_t *socks); curl_socket_t *socks);
#endif /* HEADER_CURL_HOSTIP_H */ #endif /* HEADER_CURL_HOSTIP_H */

View File

@ -89,7 +89,7 @@ bool Curl_ipvalid(struct Curl_easy *data, struct connectdata *conn)
* flavours have thread-safe versions of the plain gethostbyname() etc. * flavours have thread-safe versions of the plain gethostbyname() etc.
* *
*/ */
struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
const char *hostname, const char *hostname,
int port, int port,
int *waitp) int *waitp)
@ -97,14 +97,14 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
struct Curl_addrinfo *ai = NULL; struct Curl_addrinfo *ai = NULL;
#ifdef CURL_DISABLE_VERBOSE_STRINGS #ifdef CURL_DISABLE_VERBOSE_STRINGS
(void)conn; (void)data;
#endif #endif
*waitp = 0; /* synchronous response only */ *waitp = 0; /* synchronous response only */
ai = Curl_ipv4_resolve_r(hostname, port); ai = Curl_ipv4_resolve_r(hostname, port);
if(!ai) if(!ai)
infof(conn->data, "Curl_ipv4_resolve_r failed for %s\n", hostname); infof(data, "Curl_ipv4_resolve_r failed for %s\n", hostname);
return ai; return ai;
} }

View File

@ -127,7 +127,7 @@ static void dump_addrinfo(struct connectdata *conn,
* memory we need to free after use. That memory *MUST* be freed with * memory we need to free after use. That memory *MUST* be freed with
* Curl_freeaddrinfo(), nothing else. * Curl_freeaddrinfo(), nothing else.
*/ */
struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
const char *hostname, const char *hostname,
int port, int port,
int *waitp) int *waitp)
@ -141,14 +141,11 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
char addrbuf[128]; char addrbuf[128];
#endif #endif
int pf; int pf;
#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
struct Curl_easy *data = conn->data;
#endif
*waitp = 0; /* synchronous response only */ *waitp = 0; /* synchronous response only */
/* Check if a limited name resolve has been requested */ /* Check if a limited name resolve has been requested */
switch(conn->ip_version) { switch(data->set.ipver) {
case CURL_IPRESOLVE_V4: case CURL_IPRESOLVE_V4:
pf = PF_INET; pf = PF_INET;
break; break;
@ -166,7 +163,7 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
memset(&hints, 0, sizeof(hints)); memset(&hints, 0, sizeof(hints));
hints.ai_family = pf; hints.ai_family = pf;
hints.ai_socktype = (conn->transport == TRNSPRT_TCP) ? hints.ai_socktype = (data->conn->transport == TRNSPRT_TCP) ?
SOCK_STREAM : SOCK_DGRAM; SOCK_STREAM : SOCK_DGRAM;
#ifndef USE_RESOLVE_ON_IPS #ifndef USE_RESOLVE_ON_IPS

View File

@ -565,7 +565,7 @@ static CURLcode multi_done(struct Curl_easy *data,
conn->data = data; /* ensure the connection uses this transfer now */ conn->data = data; /* ensure the connection uses this transfer now */
/* Stop the resolver and free its own resources (but not dns_entry yet). */ /* Stop the resolver and free its own resources (but not dns_entry yet). */
Curl_resolver_kill(conn); Curl_resolver_kill(data);
/* Cleanup possible redirect junk */ /* Cleanup possible redirect junk */
Curl_safefree(data->req.newurl); Curl_safefree(data->req.newurl);
@ -995,7 +995,7 @@ static int multi_getsock(struct Curl_easy *data,
return 0; return 0;
case CURLM_STATE_WAITRESOLVE: case CURLM_STATE_WAITRESOLVE:
return Curl_resolv_getsock(conn, socks); return Curl_resolv_getsock(data, socks);
case CURLM_STATE_PROTOCONNECT: case CURLM_STATE_PROTOCONNECT:
case CURLM_STATE_SENDPROTOCONNECT: case CURLM_STATE_SENDPROTOCONNECT:
@ -1733,15 +1733,15 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(dns) { if(dns) {
#ifdef CURLRES_ASYNCH #ifdef CURLRES_ASYNCH
conn->async.dns = dns; data->state.async.dns = dns;
conn->async.done = TRUE; data->state.async.done = TRUE;
#endif #endif
result = CURLE_OK; result = CURLE_OK;
infof(data, "Hostname '%s' was found in DNS cache\n", hostname); infof(data, "Hostname '%s' was found in DNS cache\n", hostname);
} }
if(!dns) if(!dns)
result = Curl_resolv_check(data->conn, &dns); result = Curl_resolv_check(data, &dns);
/* Update sockets here, because the socket(s) may have been /* Update sockets here, because the socket(s) may have been
closed and the application thus needs to be told, even if it closed and the application thus needs to be told, even if it
@ -1754,7 +1754,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(dns) { if(dns) {
/* Perform the next step in the connection phase, and then move on /* Perform the next step in the connection phase, and then move on
to the WAITCONNECT state */ to the WAITCONNECT state */
result = Curl_once_resolved(data->conn, &protocol_connected); result = Curl_once_resolved(data, &protocol_connected);
if(result) if(result)
/* if Curl_once_resolved() returns failure, the connection struct /* if Curl_once_resolved() returns failure, the connection struct

View File

@ -238,7 +238,7 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user,
/* DNS resolve only for SOCKS4, not SOCKS4a */ /* DNS resolve only for SOCKS4, not SOCKS4a */
if(!protocol4a) { if(!protocol4a) {
enum resolve_t rc = enum resolve_t rc =
Curl_resolv(conn, hostname, remote_port, FALSE, &dns); Curl_resolv(data, hostname, remote_port, FALSE, &dns);
if(rc == CURLRESOLV_ERROR) if(rc == CURLRESOLV_ERROR)
return CURLPX_RESOLVE_HOST; return CURLPX_RESOLVE_HOST;
@ -261,14 +261,14 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user,
if(dns) { if(dns) {
#ifdef CURLRES_ASYNCH #ifdef CURLRES_ASYNCH
conn->async.dns = dns; data->state.async.dns = dns;
conn->async.done = TRUE; data->state.async.done = TRUE;
#endif #endif
infof(data, "Hostname '%s' was found\n", hostname); infof(data, "Hostname '%s' was found\n", hostname);
sxstate(data, CONNECT_RESOLVED); sxstate(data, CONNECT_RESOLVED);
} }
else { else {
result = Curl_resolv_check(data->conn, &dns); result = Curl_resolv_check(data, &dns);
if(!dns) { if(!dns) {
if(result) if(result)
return CURLPX_RESOLVE_HOST; return CURLPX_RESOLVE_HOST;
@ -754,7 +754,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
CONNECT_REQ_INIT: CONNECT_REQ_INIT:
case CONNECT_REQ_INIT: case CONNECT_REQ_INIT:
if(socks5_resolve_local) { if(socks5_resolve_local) {
enum resolve_t rc = Curl_resolv(conn, hostname, remote_port, enum resolve_t rc = Curl_resolv(data, hostname, remote_port,
FALSE, &dns); FALSE, &dns);
if(rc == CURLRESOLV_ERROR) if(rc == CURLRESOLV_ERROR)
@ -775,14 +775,14 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
if(dns) { if(dns) {
#ifdef CURLRES_ASYNCH #ifdef CURLRES_ASYNCH
conn->async.dns = dns; data->state.async.dns = dns;
conn->async.done = TRUE; data->state.async.done = TRUE;
#endif #endif
infof(data, "SOCKS5: hostname '%s' found\n", hostname); infof(data, "SOCKS5: hostname '%s' found\n", hostname);
} }
if(!dns) { if(!dns) {
result = Curl_resolv_check(data->conn, &dns); result = Curl_resolv_check(data, &dns);
if(!dns) { if(!dns) {
if(result) if(result)
return CURLPX_RESOLVE_HOST; return CURLPX_RESOLVE_HOST;

View File

@ -427,7 +427,7 @@ CURLcode Curl_close(struct Curl_easy **datap)
Curl_safefree(data->info.wouldredirect); Curl_safefree(data->info.wouldredirect);
/* this destroys the channel and we cannot use it anymore after this */ /* this destroys the channel and we cannot use it anymore after this */
Curl_resolver_cleanup(data->state.resolver); Curl_resolver_cleanup(data->state.async.resolver);
Curl_http2_cleanup_dependencies(data); Curl_http2_cleanup_dependencies(data);
Curl_convert_close(data); Curl_convert_close(data);
@ -643,7 +643,7 @@ CURLcode Curl_open(struct Curl_easy **curl)
data->magic = CURLEASY_MAGIC_NUMBER; data->magic = CURLEASY_MAGIC_NUMBER;
result = Curl_resolver_init(data, &data->state.resolver); result = Curl_resolver_init(data, &data->state.async.resolver);
if(result) { if(result) {
DEBUGF(fprintf(stderr, "Error: resolver_init failed\n")); DEBUGF(fprintf(stderr, "Error: resolver_init failed\n"));
free(data); free(data);
@ -664,7 +664,7 @@ CURLcode Curl_open(struct Curl_easy **curl)
} }
if(result) { if(result) {
Curl_resolver_cleanup(data->state.resolver); Curl_resolver_cleanup(data->state.async.resolver);
Curl_dyn_free(&data->state.headerb); Curl_dyn_free(&data->state.headerb);
Curl_freeset(data); Curl_freeset(data);
free(data); free(data);
@ -722,7 +722,7 @@ static void conn_shutdown(struct Curl_easy *data, struct connectdata *conn)
infof(data, "Closing connection %ld\n", conn->connection_id); infof(data, "Closing connection %ld\n", conn->connection_id);
/* possible left-overs from the async name resolvers */ /* possible left-overs from the async name resolvers */
Curl_resolver_cancel(conn); Curl_resolver_cancel(data);
/* close the SSL stuff before we close any sockets since they will/may /* close the SSL stuff before we close any sockets since they will/may
write to the sockets */ write to the sockets */
@ -3307,7 +3307,7 @@ static CURLcode resolve_server(struct Curl_easy *data,
conn->hostname_resolve = strdup(connhost->name); conn->hostname_resolve = strdup(connhost->name);
if(!conn->hostname_resolve) if(!conn->hostname_resolve)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
rc = Curl_resolv_timeout(conn, conn->hostname_resolve, (int)conn->port, rc = Curl_resolv_timeout(data, conn->hostname_resolve, (int)conn->port,
&hostaddr, timeout_ms); &hostaddr, timeout_ms);
if(rc == CURLRESOLV_PENDING) if(rc == CURLRESOLV_PENDING)
*async = TRUE; *async = TRUE;
@ -3332,7 +3332,7 @@ static CURLcode resolve_server(struct Curl_easy *data,
conn->hostname_resolve = strdup(host->name); conn->hostname_resolve = strdup(host->name);
if(!conn->hostname_resolve) if(!conn->hostname_resolve)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
rc = Curl_resolv_timeout(conn, conn->hostname_resolve, (int)conn->port, rc = Curl_resolv_timeout(data, conn->hostname_resolve, (int)conn->port,
&hostaddr, timeout_ms); &hostaddr, timeout_ms);
if(rc == CURLRESOLV_PENDING) if(rc == CURLRESOLV_PENDING)

View File

@ -539,15 +539,21 @@ struct hostname {
#define KEEP_RECVBITS (KEEP_RECV | KEEP_RECV_HOLD | KEEP_RECV_PAUSE) #define KEEP_RECVBITS (KEEP_RECV | KEEP_RECV_HOLD | KEEP_RECV_PAUSE)
#define KEEP_SENDBITS (KEEP_SEND | KEEP_SEND_HOLD | KEEP_SEND_PAUSE) #define KEEP_SENDBITS (KEEP_SEND | KEEP_SEND_HOLD | KEEP_SEND_PAUSE)
#if defined(CURLRES_ASYNCH) || !defined(CURL_DISABLE_DOH)
#define USE_CURL_ASYNC
struct Curl_async { struct Curl_async {
char *hostname; char *hostname;
int port;
int status; /* if done is TRUE, this is the status from the callback */
struct Curl_dns_entry *dns; struct Curl_dns_entry *dns;
struct thread_data *tdata; struct thread_data *tdata;
void *resolver; /* resolver state, if it is used in the URL state -
ares_channel f.e. */
int port;
int status; /* if done is TRUE, this is the status from the callback */
BIT(done); /* set TRUE when the lookup is complete */ BIT(done); /* set TRUE when the lookup is complete */
}; };
#endif
#define FIRSTSOCKET 0 #define FIRSTSOCKET 0
#define SECONDARYSOCKET 1 #define SECONDARYSOCKET 1
@ -1093,9 +1099,6 @@ struct connectdata {
struct negotiatedata proxyneg; /* state data for proxy Negotiate auth */ struct negotiatedata proxyneg; /* state data for proxy Negotiate auth */
#endif #endif
/* data used for the asynch name resolve callback */
struct Curl_async async;
/* for chunked-encoded trailer */ /* for chunked-encoded trailer */
struct dynbuf trailer; struct dynbuf trailer;
@ -1330,7 +1333,6 @@ struct urlpieces {
struct UrlState { struct UrlState {
/* Points to the connection cache */ /* Points to the connection cache */
struct conncache *conn_cache; struct conncache *conn_cache;
int retrycount; /* number of retries on a new connection */ int retrycount; /* number of retries on a new connection */
/* buffers to store authentication data in, as parsed from input options */ /* buffers to store authentication data in, as parsed from input options */
@ -1365,8 +1367,9 @@ struct UrlState {
struct auth authhost; /* auth details for host */ struct auth authhost; /* auth details for host */
struct auth authproxy; /* auth details for proxy */ struct auth authproxy; /* auth details for proxy */
void *resolver; /* resolver state, if it is used in the URL state - #ifdef USE_CURL_ASYNC
ares_channel f.e. */ struct Curl_async async; /* asynchronous name resolver data */
#endif
#if defined(USE_OPENSSL) #if defined(USE_OPENSSL)
/* void instead of ENGINE to avoid bleeding OpenSSL into this header */ /* void instead of ENGINE to avoid bleeding OpenSSL into this header */

View File

@ -32,7 +32,7 @@ http
HTTP GET with localhost --interface HTTP GET with localhost --interface
</name> </name>
<command> <command>
http://%HOSTIP:%HTTPPORT/1082 --interface localhost http://%HOSTIP:%HTTPPORT/1082 -4 --interface localhost
</command> </command>
<precheck> <precheck>
perl -e "print 'Test requires default test client host address' if ( '%CLIENTIP' ne '127.0.0.1' );" perl -e "print 'Test requires default test client host address' if ( '%CLIENTIP' ne '127.0.0.1' );"