/*
* 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)
- ares_cancel((ares_channel)conn->data->state.resolver);
- destroy_async_data(&conn->async);
+ if(data && data->state.async.resolver)
+ ares_cancel((ares_channel)data->state.async.resolver);
+ destroy_async_data(&data->state.async);
}
/*
* We're equivalent to Curl_resolver_cancel() for the c-ares resolver. We
* 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
at any time and we always do the same thing. */
- Curl_resolver_cancel(conn);
+ Curl_resolver_cancel(data);
}
/*
* Returns: sockets-in-use-bitmap
*/
-int Curl_resolver_getsock(struct connectdata *conn,
+int Curl_resolver_getsock(struct Curl_easy *data,
curl_socket_t *socks)
{
struct timeval maxtime;
struct timeval timebuf;
struct timeval *timeout;
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);
maxtime.tv_sec = CURL_TIMEOUT_RESOLVE;
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);
milli = (timeout->tv_sec * 1000) + (timeout->tv_usec/1000);
if(milli == 0)
milli += 10;
- Curl_expire(conn->data, milli, EXPIRE_ASYNC_NAME);
+ Curl_expire(data, milli, EXPIRE_ASYNC_NAME);
return max;
}
* 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 bitmask;
ares_socket_t socks[ARES_GETSOCK_MAXNUM];
int i;
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);
for(i = 0; i < ARES_GETSOCK_MAXNUM; i++) {
if(!nfds)
/* Call ares_process() unconditonally here, even if we simply timed out
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);
else {
/* move through the descriptors and ask for processing on them */
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].fd:ARES_SOCKET_BAD,
(pfd[i].revents & (POLLWRNORM|POLLOUT))?
*
* 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_easy *data = conn->data;
- struct thread_data *res = conn->async.tdata;
+ struct thread_data *res = data->state.async.tdata;
CURLcode result = CURLE_OK;
DEBUGASSERT(dns);
*dns = NULL;
- waitperform(conn, 0);
+ waitperform(data, 0);
/* 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
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.resolver);
+ ares_cancel((ares_channel)data->state.async.resolver);
DEBUGASSERT(res->num_pending == 0);
}
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
them */
res->temp_ai = NULL;
- if(!conn->async.dns) {
+ if(!data->state.async.dns) {
failf(data, "Could not resolve: %s (%s)",
- conn->async.hostname, ares_strerror(conn->async.status));
- result = conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
+ data->state.async.hostname,
+ ares_strerror(data->state.async.status));
+ result = data->conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
CURLE_COULDNT_RESOLVE_HOST;
}
else
- *dns = conn->async.dns;
+ *dns = data->state.async.dns;
- destroy_async_data(&conn->async);
+ destroy_async_data(&data->state.async);
}
return result;
* Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved,
* 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)
{
CURLcode result = CURLE_OK;
- struct Curl_easy *data = conn->data;
timediff_t timeout;
struct curltime now = Curl_now();
timeout = Curl_timeleft(data, &now, TRUE);
if(timeout < 0) {
/* already expired! */
- connclose(conn, "Timed out before name resolve started");
+ connclose(data->conn, "Timed out before name resolve started");
return CURLE_OPERATION_TIMEDOUT;
}
if(!timeout)
store.tv_sec = itimeout/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
second is left, otherwise just use 1000ms to make sure the progress
else
timeout_ms = 1000;
- waitperform(conn, timeout_ms);
- result = Curl_resolver_is_resolved(conn, entry);
+ waitperform(data, timeout_ms);
+ result = Curl_resolver_is_resolved(data, entry);
- if(result || conn->async.done)
+ if(result || data->state.async.done)
break;
if(Curl_pgrsUpdate(data))
}
if(result)
/* 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
in the cache. */
if(entry)
- *entry = conn->async.dns;
+ *entry = data->state.async.dns;
if(result)
/* close the connection, since we can't return failure here without
cleaning up this connection properly. */
- connclose(conn, "c-ares resolve failed");
+ connclose(data->conn, "c-ares resolve failed");
return result;
}
#endif
struct hostent *hostent)
{
- struct connectdata *conn = (struct connectdata *)arg;
+ struct Curl_easy *data = (struct Curl_easy *)arg;
struct thread_data *res;
#ifdef HAVE_CARES_CALLBACK_TIMEOUTS
be valid so only defer it when we know the 'status' says its fine! */
return;
- res = conn->async.tdata;
+ res = data->state.async.tdata;
if(res) {
res->num_pending--;
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) {
compound_results(res, ai);
}
c-ares retry cycle each request is.
*/
res->happy_eyeballs_dns_time = Curl_now();
- Curl_expire(
- conn->data, HAPPY_EYEBALLS_DNS_TIMEOUT, EXPIRE_HAPPY_EYEBALLS_DNS);
+ Curl_expire(data, HAPPY_EYEBALLS_DNS_TIMEOUT,
+ EXPIRE_HAPPY_EYEBALLS_DNS);
}
}
}
* memory we need to free after use. That memory *MUST* be freed with
* 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,
int port,
int *waitp)
{
char *bufp;
- struct Curl_easy *data = conn->data;
int family = PF_INET;
*waitp = 0; /* default to synchronous response */
#ifdef ENABLE_IPV6
- switch(conn->ip_version) {
+ switch(data->set.ipver) {
default:
#if ARES_VERSION >= 0x010601
family = PF_UNSPEC; /* supported by c-ares since 1.6.1, so for older
bufp = strdup(hostname);
if(bufp) {
struct thread_data *res = NULL;
- 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 */
+ free(data->state.async.hostname);
+ data->state.async.hostname = bufp;
+ data->state.async.port = port;
+ data->state.async.done = FALSE; /* not done */
+ data->state.async.status = 0; /* clear */
+ data->state.async.dns = NULL; /* clear */
res = calloc(sizeof(struct thread_data), 1);
if(!res) {
- free(conn->async.hostname);
- conn->async.hostname = NULL;
+ free(data->state.async.hostname);
+ data->state.async.hostname = NULL;
return NULL;
}
- conn->async.tdata = res;
+ data->state.async.tdata = res;
/* initial status - failed */
res->last_status = ARES_ENOTFOUND;
res->num_pending = 2;
/* areschannel is already setup in the Curl_open() function */
- ares_gethostbyname((ares_channel)data->state.resolver, hostname,
- PF_INET, query_completed_cb, conn);
- ares_gethostbyname((ares_channel)data->state.resolver, hostname,
- PF_INET6, query_completed_cb, conn);
+ 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);
}
else {
res->num_pending = 1;
/* areschannel is already setup in the Curl_open() function */
- ares_gethostbyname((ares_channel)data->state.resolver, hostname,
- PF_INET, query_completed_cb, conn);
+ ares_gethostbyname((ares_channel)data->state.async.resolver, hostname,
+ PF_INET, query_completed_cb, data);
}
}
else
res->num_pending = 1;
/* areschannel is already setup in the Curl_open() function */
- ares_gethostbyname((ares_channel)data->state.resolver, hostname, family,
- query_completed_cb, conn);
+ ares_gethostbyname((ares_channel)data->state.async.resolver,
+ hostname, family,
+ query_completed_cb, data);
}
*waitp = 1; /* expect asynchronous response */
#if (ARES_VERSION >= 0x010704)
#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
- ares_result = ares_set_servers_csv(data->state.resolver, servers);
+ ares_result = ares_set_servers_csv(data->state.async.resolver, servers);
#endif
switch(ares_result) {
case ARES_SUCCESS:
if(!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;
#else /* c-ares version too old! */
}
}
- 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;
#else /* c-ares version too old! */
}
}
- ares_set_local_ip6((ares_channel)data->state.resolver, a6);
+ ares_set_local_ip6((ares_channel)data->state.async.resolver, a6);
return CURLE_OK;
#else /* c-ares version too old! */
/*
* 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 */
-static bool init_resolve_thread(struct connectdata *conn,
+static bool init_resolve_thread(struct Curl_easy *data,
const char *hostname, int port,
const struct addrinfo *hints);
char *hostname; /* hostname to resolve, Curl_async.hostname
duplicate */
#ifdef USE_SOCKETPAIR
- struct connectdata *conn;
+ struct Curl_easy *data;
curl_socket_t sock_pair[2]; /* socket pair */
#endif
int sock_error;
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 */
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;
- 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
cache. Set our copy to NULL so destroy_thread_sync_data doesn't free it.
*/
int done;
#ifdef USE_SOCKETPAIR
curl_socket_t sock_rd = td->tsd.sock_pair[0];
- struct connectdata *conn = td->tsd.conn;
+ struct Curl_easy *data = td->tsd.data;
#endif
/*
* ensure CURLMOPT_SOCKETFUNCTION fires CURL_POLL_REMOVE
* before the FD is invalidated to avoid EBADF on EPOLL_CTL_DEL
*/
- if(conn)
- Curl_multi_closed(conn->data, sock_rd);
+ Curl_multi_closed(data, sock_rd);
sclose(sock_rd);
#endif
}
*
* 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 struct addrinfo *hints)
{
struct thread_data *td = calloc(1, sizeof(struct thread_data));
int err = ENOMEM;
+ struct Curl_async *asp = &data->state.async;
- conn->async.tdata = td;
+ data->state.async.tdata = td;
if(!td)
goto errno_exit;
- conn->async.port = port;
- conn->async.done = FALSE;
- conn->async.status = 0;
- conn->async.dns = NULL;
+ asp->port = port;
+ asp->done = FALSE;
+ asp->status = 0;
+ asp->dns = NULL;
td->thread_hnd = curl_thread_t_null;
if(!init_thread_sync_data(td, hostname, port, hints)) {
- conn->async.tdata = NULL;
+ asp->tdata = NULL;
free(td);
goto errno_exit;
}
- free(conn->async.hostname);
- conn->async.hostname = strdup(hostname);
- if(!conn->async.hostname)
+ free(asp->hostname);
+ asp->hostname = strdup(hostname);
+ if(!asp->hostname)
goto err_exit;
/* The thread will set this to 1 when complete. */
return TRUE;
err_exit:
- destroy_async_data(&conn->async);
+ destroy_async_data(asp);
errno_exit:
errno = err;
* error
*/
-static CURLcode resolver_error(struct connectdata *conn)
+static CURLcode resolver_error(struct Curl_easy *data)
{
const char *host_or_proxy;
CURLcode result;
#ifndef CURL_DISABLE_PROXY
+ struct connectdata *conn = data->conn;
if(conn->bits.httpproxy) {
host_or_proxy = "proxy";
result = CURLE_COULDNT_RESOLVE_PROXY;
result = CURLE_COULDNT_RESOLVE_HOST;
}
- failf(conn->data, "Could not resolve %s: %s", host_or_proxy,
- conn->async.hostname);
+ failf(data, "Could not resolve %s: %s", host_or_proxy,
+ data->state.async.hostname);
return result;
}
/*
* '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,
bool report)
{
- struct thread_data *td = conn->async.tdata;
+ struct thread_data *td;
CURLcode result = CURLE_OK;
- DEBUGASSERT(conn && td);
+ DEBUGASSERT(data);
+ td = data->state.async.tdata;
+ DEBUGASSERT(td);
DEBUGASSERT(td->thread_hnd != curl_thread_t_null);
/* wait for the thread to resolve the name */
if(Curl_thread_join(&td->thread_hnd)) {
if(entry)
- result = getaddrinfo_complete(conn);
+ result = getaddrinfo_complete(data);
}
else
DEBUGASSERT(0);
- conn->async.done = TRUE;
+ data->state.async.done = TRUE;
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 */
- result = resolver_error(conn);
+ result = resolver_error(data);
- destroy_async_data(&conn->async);
+ destroy_async_data(&data->state.async);
- if(!conn->async.dns && report)
- connclose(conn, "asynch resolve failed");
+ if(!data->state.async.dns && report)
+ connclose(data->conn, "asynch resolve failed");
return result;
}
* Until we gain a way to signal the resolver threads to stop early, we must
* 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,
unfortunately. Otherwise, we can simply cancel to clean up any resolver
data. */
if(td && td->thread_hnd != curl_thread_t_null)
- (void)thread_wait_resolv(conn, NULL, FALSE);
+ (void)thread_wait_resolv(data, NULL, FALSE);
else
- Curl_resolver_cancel(conn);
+ Curl_resolver_cancel(data);
}
/*
*
* 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)
{
- return thread_wait_resolv(conn, entry, TRUE);
+ return thread_wait_resolv(data, entry, TRUE);
}
/*
* name resolve request has completed. It should also make sure to time-out if
* 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_easy *data = conn->data;
- struct thread_data *td = conn->async.tdata;
+ struct thread_data *td = data->state.async.tdata;
int done = 0;
DEBUGASSERT(entry);
Curl_mutex_release(td->tsd.mtx);
if(done) {
- getaddrinfo_complete(conn);
+ getaddrinfo_complete(data);
- if(!conn->async.dns) {
- CURLcode result = resolver_error(conn);
- destroy_async_data(&conn->async);
+ if(!data->state.async.dns) {
+ CURLcode result = resolver_error(data);
+ destroy_async_data(&data->state.async);
return result;
}
- destroy_async_data(&conn->async);
- *entry = conn->async.dns;
+ destroy_async_data(&data->state.async);
+ *entry = data->state.async.dns;
}
else {
/* poll for name lookup done with exponential backoff up to 250ms */
td->poll_interval = 250;
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;
}
-int Curl_resolver_getsock(struct connectdata *conn,
- curl_socket_t *socks)
+int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *socks)
{
int ret_val = 0;
timediff_t milli;
timediff_t ms;
- struct Curl_easy *data = conn->data;
- struct resdata *reslv = (struct resdata *)data->state.resolver;
+ struct resdata *reslv = (struct resdata *)data->state.async.resolver;
#ifdef USE_SOCKETPAIR
- struct thread_data *td = conn->async.tdata;
+ struct thread_data *td = data->state.async.tdata;
#else
(void)socks;
#endif
if(td) {
/* return read fd to client for polling the DNS resolution status */
socks[0] = td->tsd.sock_pair[0];
- DEBUGASSERT(td->tsd.conn == conn || !td->tsd.conn);
- td->tsd.conn = conn;
+ td->tsd.data = data;
ret_val = GETSOCK_READSOCK(0);
}
else {
/*
* 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,
int port,
int *waitp)
{
- struct Curl_easy *data = conn->data;
struct resdata *reslv = (struct resdata *)data->state.resolver;
*waitp = 0; /* default to synchronous response */
reslv->start = Curl_now();
/* 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 */
return NULL;
}
/*
* 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,
int port,
int *waitp)
{
struct addrinfo hints;
int pf = PF_INET;
- struct Curl_easy *data = conn->data;
- struct resdata *reslv = (struct resdata *)data->state.resolver;
+ struct resdata *reslv = (struct resdata *)data->state.async.resolver;
*waitp = 0; /* default to synchronous response */
/*
* Check if a limited name resolve has been requested.
*/
- switch(conn->ip_version) {
+ switch(data->set.ipver) {
case CURL_IPRESOLVE_V4:
pf = PF_INET;
break;
memset(&hints, 0, sizeof(hints));
hints.ai_family = pf;
- hints.ai_socktype = (conn->transport == TRNSPRT_TCP)?
+ hints.ai_socktype = (data->conn->transport == TRNSPRT_TCP)?
SOCK_STREAM : SOCK_DGRAM;
reslv->start = Curl_now();
/* 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 */
return NULL;
}
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
* you should have received as part of this distribution. The terms
*
* 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().
*
* 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()
*
* return bitmask indicating what file descriptors (referring to array indexes
* 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()
*
* 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);
/*
* Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved,
* 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);
/*
* Each resolver backend must of course make sure to return data in the
* 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,
int port,
int *waitp);
conn->ip_version = CURL_IPRESOLVE_V6;
#endif
- rc = Curl_resolv(conn, dev, 0, FALSE, &h);
+ rc = Curl_resolv(data, dev, 0, FALSE, &h);
if(rc == CURLRESOLV_PENDING)
- (void)Curl_resolver_wait_resolv(conn, &h);
+ (void)Curl_resolver_wait_resolv(data, &h);
conn->ip_version = ipver;
if(h) {
* '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,
int port,
int *waitp)
{
- struct Curl_easy *data = conn->data;
CURLcode result = CURLE_OK;
int slot;
struct dohdata *dohp;
+ struct connectdata *conn = data->conn;
*waitp = TRUE; /* this never returns synchronously */
- (void)conn;
(void)hostname;
(void)port;
DEBUGASSERT(!data->req.doh);
+ DEBUGASSERT(conn);
/* start clean, consider allocating this struct on demand */
dohp = data->req.doh = calloc(sizeof(struct dohdata), 1);
}
}
-CURLcode Curl_doh_is_resolved(struct connectdata *conn,
+CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
struct Curl_dns_entry **dnsp)
{
CURLcode result;
- struct Curl_easy *data = conn->data;
struct dohdata *dohp = data->req.doh;
*dnsp = NULL; /* defaults to no response */
if(!dohp)
if(!dohp->probe[DOH_PROBE_SLOT_IPADDR_V4].easy &&
!dohp->probe[DOH_PROBE_SLOT_IPADDR_V6].easy) {
- failf(data, "Could not DOH-resolve: %s", conn->async.hostname);
- return conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
+ failf(data, "Could not DOH-resolve: %s", data->state.async.hostname);
+ return data->conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
CURLE_COULDNT_RESOLVE_HOST;
}
else if(!dohp->pending) {
Curl_freeaddrinfo(ai);
}
else {
- conn->async.dns = dns;
+ data->state.async.dns = dns;
*dnsp = dns;
result = CURLE_OK; /* address resolution OK */
}
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
* you should have received as part of this distribution. The terms
* 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,
int port,
int *waitp);
-CURLcode Curl_doh_is_resolved(struct connectdata *conn,
+CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
struct Curl_dns_entry **dns);
int Curl_doh_getsock(struct connectdata *conn, curl_socket_t *socks);
#endif
/* Clone the resolver handle, if present, for the new handle */
if(Curl_resolver_duphandle(outcurl,
- &outcurl->state.resolver,
- data->state.resolver))
+ &outcurl->state.async.resolver,
+ data->state.async.resolver))
goto fail;
#ifdef USE_ARES
}
/* 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)
- (void)Curl_resolver_wait_resolv(conn, &h);
+ (void)Curl_resolver_wait_resolv(data, &h);
if(h) {
res = h->addr;
/* when we return from this function, we can forget about this entry
*/
const char * const host_name = conn->bits.socksproxy ?
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)
/* BLOCKING, ignores the return code but 'addr' will be NULL in
case of failure */
- (void)Curl_resolver_wait_resolv(conn, &addr);
+ (void)Curl_resolver_wait_resolv(data, &addr);
connectport =
(unsigned short)conn->port; /* we connect to the proxy's port */
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)
/* BLOCKING */
- (void)Curl_resolver_wait_resolv(conn, &addr);
+ (void)Curl_resolver_wait_resolv(data, &addr);
connectport = ftpc->newport; /* we connect to the remote port */
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
* you should have received as part of this distribution. The terms
*
* 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,
struct Curl_addrinfo *ai)
{
struct Curl_dns_entry *dns = NULL;
CURLcode result = CURLE_OK;
- conn->async.status = status;
+ data->state.async.status = status;
if(CURL_ASYNC_SUCCESS == status) {
if(ai) {
- struct Curl_easy *data = conn->data;
-
if(data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
dns = Curl_cache_addr(data, ai,
- conn->async.hostname,
- conn->async.port);
+ data->state.async.hostname,
+ data->state.async.port);
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
}
}
- conn->async.dns = dns;
+ data->state.async.dns = dns;
/* 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
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
this function */
* name resolve layers (selected at build-time). They all take this same set
* of arguments
*/
-struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
+struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
const char *hostname,
int port,
int *waitp)
{
- return Curl_resolver_getaddrinfo(conn, hostname, port, waitp);
+ return Curl_resolver_getaddrinfo(data, hostname, port, waitp);
}
#endif /* CURLRES_ASYNCH */
#endif
/* lookup address, returns entry if found and not stale */
-static struct Curl_dns_entry *
-fetch_addr(struct connectdata *conn,
- const char *hostname,
- int port)
+static struct Curl_dns_entry *fetch_addr(struct Curl_easy *data,
+ const char *hostname,
+ int port)
{
struct Curl_dns_entry *dns = NULL;
size_t entry_len;
- struct Curl_easy *data = conn->data;
char entry_id[MAX_HOSTCACHE_LEN];
/* Create an entry id, based upon the hostname and port */
if(data->share)
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)
dns->inuse++; /* we use it! */
* 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,
int port,
bool allowDOH,
struct Curl_dns_entry **entry)
{
struct Curl_dns_entry *dns = NULL;
- struct Curl_easy *data = conn->data;
CURLcode result;
enum resolve_t rc = CURLRESOLV_ERROR; /* default to failure */
+ struct connectdata *conn = data->conn;
*entry = NULL;
conn->bits.doh = FALSE; /* default is not */
if(data->share)
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) {
infof(data, "Hostname %s was found in DNS cache\n", hostname);
if(data->set.resolver_start) {
int st;
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);
Curl_set_in_callback(data, false);
if(st)
return CURLRESOLV_ERROR;
if(allowDOH && data->set.doh && !ipnum) {
- addr = Curl_doh(conn, hostname, port, &respwait);
+ addr = Curl_doh(data, hostname, port, &respwait);
}
else {
/* If Curl_getaddrinfo() returns NULL, 'respwait' might be set to a
non-zero value indicating that we need to wait for the response to
the resolve call */
- addr = Curl_getaddrinfo(conn,
+ addr = Curl_getaddrinfo(data,
#ifdef DEBUGBUILD
(data->set.str[STRING_DEVICE]
&& !strcmp(data->set.str[STRING_DEVICE],
/* the response to our resolve call will come asynchronously at
a later time, good or bad */
/* 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 */
return CURLRESOLV_ERROR;
if(dns)
* 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,
int port,
struct Curl_dns_entry **entry,
#endif /* HAVE_SIGACTION */
volatile long timeout;
volatile unsigned int prev_alarm = 0;
- struct Curl_easy *data = conn->data;
#endif /* USE_ALARM_TIMEOUT */
enum resolve_t rc;
if(!timeout)
/* 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) {
/* The alarm() function only provides integer second resolution, so if
#else
#ifndef CURLRES_ASYNCH
if(timeoutms)
- infof(conn->data, "timeout on name lookup is not supported\n");
+ infof(data, "timeout on name lookup is not supported\n");
#else
(void)timeoutms; /* timeoutms not used with an async resolver */
#endif
/* Perform the actual name resolution. This might be interrupted by an
* 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
clean_up:
if(prev_alarm) {
/* there was an alarm() set before us, now put it back */
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 */
unsigned long alarm_set = (unsigned long)(prev_alarm - elapsed_secs);
return CURLE_OK;
}
-CURLcode Curl_resolv_check(struct connectdata *conn,
+CURLcode Curl_resolv_check(struct Curl_easy *data,
struct Curl_dns_entry **dns)
{
#if defined(CURL_DISABLE_DOH) && !defined(CURLRES_ASYNCH)
(void)dns;
#endif
- if(conn->bits.doh)
- return Curl_doh_is_resolved(conn, dns);
- return Curl_resolver_is_resolved(conn, dns);
+ if(data->conn->bits.doh)
+ return Curl_doh_is_resolved(data, 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)
{
#ifdef CURLRES_ASYNCH
- if(conn->bits.doh)
+ if(data->conn->bits.doh)
/* nothing to wait for during DOH resolve, those handles have their own
sockets */
return GETSOCK_BLANK;
- return Curl_resolver_getsock(conn, socks);
+ return Curl_resolver_getsock(data, socks);
#else
- (void)conn;
+ (void)data;
(void)socks;
return GETSOCK_BLANK;
#endif
Note: this function disconnects and frees the conn data in case of
resolve failure */
-CURLcode Curl_once_resolved(struct connectdata *conn,
- bool *protocol_done)
+CURLcode Curl_once_resolved(struct Curl_easy *data, bool *protocol_done)
{
CURLcode result;
+ struct connectdata *conn = data->conn;
- if(conn->async.dns) {
- conn->dns_entry = conn->async.dns;
- conn->async.dns = NULL;
+ if(data->state.async.dns) {
+ conn->dns_entry = data->state.async.dns;
+ data->state.async.dns = NULL;
}
result = Curl_setup_conn(conn, protocol_done);
if(result) {
- struct Curl_easy *data = conn->data;
- DEBUGASSERT(data);
Curl_detach_connnection(data);
Curl_conncache_remove_conn(data, conn, TRUE);
Curl_disconnect(data, conn, TRUE);
CURLRESOLV_RESOLVED = 0,
CURLRESOLV_PENDING = 1
};
-enum resolve_t Curl_resolv(struct connectdata *conn,
+enum resolve_t Curl_resolv(struct Curl_easy *data,
const char *hostname,
int port,
bool allowDOH,
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,
struct Curl_dns_entry **dnsentry,
timediff_t timeoutms);
* name resolve layers (selected at build-time). They all take this same set
* of arguments
*/
-struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
+struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
const char *hostname,
int port,
int *waitp);
/* IPv4 threadsafe resolve function used for synch and asynch builds */
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.
* status is CURL_ASYNC_SUCCESS. Twiddles fields in conn to indicate async
* request completed whether successful or failed.
*/
-CURLcode Curl_addrinfo_callback(struct connectdata *conn,
+CURLcode Curl_addrinfo_callback(struct Curl_easy *data,
int status,
struct Curl_addrinfo *ai);
* Populate the cache with specified entries from CURLOPT_RESOLVE.
*/
CURLcode Curl_loadhostpairs(struct Curl_easy *data);
-
-CURLcode Curl_resolv_check(struct connectdata *conn,
+CURLcode Curl_resolv_check(struct Curl_easy *data,
struct Curl_dns_entry **dns);
-int Curl_resolv_getsock(struct connectdata *conn,
+int Curl_resolv_getsock(struct Curl_easy *data,
curl_socket_t *socks);
#endif /* HEADER_CURL_HOSTIP_H */
* 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,
int port,
int *waitp)
struct Curl_addrinfo *ai = NULL;
#ifdef CURL_DISABLE_VERBOSE_STRINGS
- (void)conn;
+ (void)data;
#endif
*waitp = 0; /* synchronous response only */
ai = Curl_ipv4_resolve_r(hostname, port);
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;
}
* memory we need to free after use. That memory *MUST* be freed with
* Curl_freeaddrinfo(), nothing else.
*/
-struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
+struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
const char *hostname,
int port,
int *waitp)
char addrbuf[128];
#endif
int pf;
-#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
- struct Curl_easy *data = conn->data;
-#endif
*waitp = 0; /* synchronous response only */
/* Check if a limited name resolve has been requested */
- switch(conn->ip_version) {
+ switch(data->set.ipver) {
case CURL_IPRESOLVE_V4:
pf = PF_INET;
break;
memset(&hints, 0, sizeof(hints));
hints.ai_family = pf;
- hints.ai_socktype = (conn->transport == TRNSPRT_TCP) ?
+ hints.ai_socktype = (data->conn->transport == TRNSPRT_TCP) ?
SOCK_STREAM : SOCK_DGRAM;
#ifndef USE_RESOLVE_ON_IPS
conn->data = data; /* ensure the connection uses this transfer now */
/* 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 */
Curl_safefree(data->req.newurl);
return 0;
case CURLM_STATE_WAITRESOLVE:
- return Curl_resolv_getsock(conn, socks);
+ return Curl_resolv_getsock(data, socks);
case CURLM_STATE_PROTOCONNECT:
case CURLM_STATE_SENDPROTOCONNECT:
if(dns) {
#ifdef CURLRES_ASYNCH
- conn->async.dns = dns;
- conn->async.done = TRUE;
+ data->state.async.dns = dns;
+ data->state.async.done = TRUE;
#endif
result = CURLE_OK;
infof(data, "Hostname '%s' was found in DNS cache\n", hostname);
}
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
closed and the application thus needs to be told, even if it
if(dns) {
/* Perform the next step in the connection phase, and then move on
to the WAITCONNECT state */
- result = Curl_once_resolved(data->conn, &protocol_connected);
+ result = Curl_once_resolved(data, &protocol_connected);
if(result)
/* if Curl_once_resolved() returns failure, the connection struct
/* DNS resolve only for SOCKS4, not SOCKS4a */
if(!protocol4a) {
enum resolve_t rc =
- Curl_resolv(conn, hostname, remote_port, FALSE, &dns);
+ Curl_resolv(data, hostname, remote_port, FALSE, &dns);
if(rc == CURLRESOLV_ERROR)
return CURLPX_RESOLVE_HOST;
if(dns) {
#ifdef CURLRES_ASYNCH
- conn->async.dns = dns;
- conn->async.done = TRUE;
+ data->state.async.dns = dns;
+ data->state.async.done = TRUE;
#endif
infof(data, "Hostname '%s' was found\n", hostname);
sxstate(data, CONNECT_RESOLVED);
}
else {
- result = Curl_resolv_check(data->conn, &dns);
+ result = Curl_resolv_check(data, &dns);
if(!dns) {
if(result)
return CURLPX_RESOLVE_HOST;
CONNECT_REQ_INIT:
case CONNECT_REQ_INIT:
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);
if(rc == CURLRESOLV_ERROR)
if(dns) {
#ifdef CURLRES_ASYNCH
- conn->async.dns = dns;
- conn->async.done = TRUE;
+ data->state.async.dns = dns;
+ data->state.async.done = TRUE;
#endif
infof(data, "SOCKS5: hostname '%s' found\n", hostname);
}
if(!dns) {
- result = Curl_resolv_check(data->conn, &dns);
+ result = Curl_resolv_check(data, &dns);
if(!dns) {
if(result)
return CURLPX_RESOLVE_HOST;
Curl_safefree(data->info.wouldredirect);
/* 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_convert_close(data);
data->magic = CURLEASY_MAGIC_NUMBER;
- result = Curl_resolver_init(data, &data->state.resolver);
+ result = Curl_resolver_init(data, &data->state.async.resolver);
if(result) {
DEBUGF(fprintf(stderr, "Error: resolver_init failed\n"));
free(data);
}
if(result) {
- Curl_resolver_cleanup(data->state.resolver);
+ Curl_resolver_cleanup(data->state.async.resolver);
Curl_dyn_free(&data->state.headerb);
Curl_freeset(data);
free(data);
infof(data, "Closing connection %ld\n", conn->connection_id);
/* 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
write to the sockets */
conn->hostname_resolve = strdup(connhost->name);
if(!conn->hostname_resolve)
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);
if(rc == CURLRESOLV_PENDING)
*async = TRUE;
conn->hostname_resolve = strdup(host->name);
if(!conn->hostname_resolve)
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);
if(rc == CURLRESOLV_PENDING)
#define KEEP_RECVBITS (KEEP_RECV | KEEP_RECV_HOLD | KEEP_RECV_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 {
char *hostname;
- int port;
- int status; /* if done is TRUE, this is the status from the callback */
struct Curl_dns_entry *dns;
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 */
};
+#endif
+
#define FIRSTSOCKET 0
#define SECONDARYSOCKET 1
struct negotiatedata proxyneg; /* state data for proxy Negotiate auth */
#endif
- /* data used for the asynch name resolve callback */
- struct Curl_async async;
-
/* for chunked-encoded trailer */
struct dynbuf trailer;
struct UrlState {
/* Points to the connection cache */
struct conncache *conn_cache;
-
int retrycount; /* number of retries on a new connection */
/* buffers to store authentication data in, as parsed from input options */
struct auth authhost; /* auth details for host */
struct auth authproxy; /* auth details for proxy */
- void *resolver; /* resolver state, if it is used in the URL state -
- ares_channel f.e. */
+#ifdef USE_CURL_ASYNC
+ struct Curl_async async; /* asynchronous name resolver data */
+#endif
#if defined(USE_OPENSSL)
/* void instead of ENGINE to avoid bleeding OpenSSL into this header */
HTTP GET with localhost --interface
</name>
<command>
-http://%HOSTIP:%HTTPPORT/1082 --interface localhost
+http://%HOSTIP:%HTTPPORT/1082 -4 --interface localhost
</command>
<precheck>
perl -e "print 'Test requires default test client host address' if ( '%CLIENTIP' ne '127.0.0.1' );"