From 8335c6417ea21bdfc340f0cb8cab5dbc97b10a2e Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 20 Jan 2021 10:15:43 +0100 Subject: [PATCH] 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 --- lib/asyn-ares.c | 132 +++++++++++++++++++++---------------------- lib/asyn-thread.c | 135 ++++++++++++++++++++++---------------------- lib/asyn.h | 14 ++--- lib/connect.c | 4 +- lib/doh.c | 15 +++-- lib/doh.h | 6 +- lib/easy.c | 4 +- lib/ftp.c | 12 ++-- lib/hostasyn.c | 20 +++---- lib/hostip.c | 63 ++++++++++----------- lib/hostip.h | 15 +++-- lib/hostip4.c | 6 +- lib/hostip6.c | 9 +-- lib/multi.c | 12 ++-- lib/socks.c | 16 +++--- lib/url.c | 12 ++-- lib/urldata.h | 19 ++++--- tests/data/test1082 | 2 +- 18 files changed, 242 insertions(+), 254 deletions(-) diff --git a/lib/asyn-ares.c b/lib/asyn-ares.c index c17cd265b3..2484a7b498 100644 --- a/lib/asyn-ares.c +++ b/lib/asyn-ares.c @@ -204,22 +204,22 @@ static void destroy_async_data(struct Curl_async *async); /* * Cancel all possibly still on-going resolves for this connection. */ -void Curl_resolver_cancel(struct connectdata *conn) +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); } /* @@ -253,25 +253,25 @@ static void destroy_async_data(struct Curl_async *async) * 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; } @@ -286,9 +286,8 @@ int Curl_resolver_getsock(struct connectdata *conn, * 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]; @@ -296,7 +295,7 @@ static int waitperform(struct connectdata *conn, timediff_t timeout_ms) 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++) { @@ -324,12 +323,12 @@ static int waitperform(struct connectdata *conn, timediff_t timeout_ms) 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))? @@ -345,17 +344,16 @@ static int waitperform(struct connectdata *conn, timediff_t timeout_ms) * * 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 @@ -376,26 +374,27 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn, 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; @@ -412,11 +411,10 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn, * 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(); @@ -426,7 +424,7 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, 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) @@ -447,7 +445,7 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, 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 @@ -457,10 +455,10 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, 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)) @@ -481,17 +479,17 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, } 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; } @@ -525,7 +523,7 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */ #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 @@ -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! */ 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); } @@ -607,8 +605,8 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */ 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); } } } @@ -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 * 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 @@ -653,19 +650,19 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, 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; @@ -675,17 +672,17 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, 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 @@ -694,8 +691,9 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, 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 */ @@ -720,9 +718,10 @@ CURLcode Curl_set_dns_servers(struct Curl_easy *data, #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: @@ -752,7 +751,7 @@ CURLcode Curl_set_dns_interface(struct Curl_easy *data, 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! */ @@ -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; #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; #else /* c-ares version too old! */ diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c index 9caa1be099..e79aa9127b 100644 --- a/lib/asyn-thread.c +++ b/lib/asyn-thread.c @@ -145,13 +145,13 @@ static void destroy_async_data(struct Curl_async *); /* * 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); @@ -164,7 +164,7 @@ struct thread_sync_data { 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; @@ -182,9 +182,9 @@ struct thread_data { 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 */ @@ -268,12 +268,12 @@ int init_thread_sync_data(struct thread_data *td, 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. */ @@ -384,7 +384,7 @@ static void destroy_async_data(struct Curl_async *async) 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 /* @@ -412,8 +412,7 @@ static void destroy_async_data(struct Curl_async *async) * 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 } @@ -429,32 +428,33 @@ static void destroy_async_data(struct Curl_async *async) * * 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. */ @@ -476,7 +476,7 @@ static bool init_resolve_thread(struct connectdata *conn, return TRUE; err_exit: - destroy_async_data(&conn->async); + destroy_async_data(asp); errno_exit: errno = err; @@ -488,12 +488,13 @@ static bool init_resolve_thread(struct connectdata *conn, * 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; @@ -505,8 +506,8 @@ static CURLcode resolver_error(struct connectdata *conn) 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; } @@ -514,37 +515,39 @@ static CURLcode resolver_error(struct connectdata *conn) /* * '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; } @@ -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 * 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); } /* @@ -580,10 +583,10 @@ void Curl_resolver_kill(struct connectdata *conn) * * 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); } /* @@ -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 * 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); @@ -611,15 +613,15 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn, 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 */ @@ -640,22 +642,20 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn, 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 @@ -664,8 +664,7 @@ int Curl_resolver_getsock(struct connectdata *conn, 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 { @@ -692,12 +691,11 @@ int Curl_resolver_getsock(struct connectdata *conn, /* * 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 */ @@ -705,7 +703,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, 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; } @@ -720,15 +718,14 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, /* * 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 */ @@ -736,7 +733,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, /* * 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; @@ -755,12 +752,12 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, 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; } diff --git a/lib/asyn.h b/lib/asyn.h index 73a9b7268f..3130395826 100644 --- a/lib/asyn.h +++ b/lib/asyn.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * 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. */ -void Curl_resolver_cancel(struct connectdata *conn); +void Curl_resolver_cancel(struct Curl_easy *data); /* * 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. */ -void Curl_resolver_kill(struct connectdata *conn); +void Curl_resolver_kill(struct Curl_easy *data); /* Curl_resolver_getsock() * @@ -114,7 +114,7 @@ void Curl_resolver_kill(struct connectdata *conn); * 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() @@ -125,7 +125,7 @@ int Curl_resolver_getsock(struct connectdata *conn, curl_socket_t *sock); * * 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); /* @@ -139,7 +139,7 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn, * 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); /* @@ -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 * 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); diff --git a/lib/connect.c b/lib/connect.c index 81ae006e86..052542449a 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -358,9 +358,9 @@ static CURLcode bindlocal(struct Curl_easy *data, 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) { diff --git a/lib/doh.c b/lib/doh.c index 608f3d94c4..004244c8d2 100644 --- a/lib/doh.c +++ b/lib/doh.c @@ -379,21 +379,21 @@ static CURLcode dohprobe(struct Curl_easy *data, * '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); @@ -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) { CURLcode result; - struct Curl_easy *data = conn->data; struct dohdata *dohp = data->req.doh; *dnsp = NULL; /* defaults to no response */ if(!dohp) @@ -923,8 +922,8 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn, 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) { @@ -984,7 +983,7 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn, Curl_freeaddrinfo(ai); } else { - conn->async.dns = dns; + data->state.async.dns = dns; *dnsp = dns; result = CURLE_OK; /* address resolution OK */ } diff --git a/lib/doh.h b/lib/doh.h index 0867584ced..b3584d1b27 100644 --- a/lib/doh.h +++ b/lib/doh.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2018 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 2018 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -32,12 +32,12 @@ * 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); diff --git a/lib/easy.c b/lib/easy.c index 3b72ce7a44..0fb255af49 100644 --- a/lib/easy.c +++ b/lib/easy.c @@ -908,8 +908,8 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) #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 diff --git a/lib/ftp.c b/lib/ftp.c index 29566fb2f7..6a1cf4df97 100644 --- a/lib/ftp.c +++ b/lib/ftp.c @@ -1079,9 +1079,9 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data, } /* 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 @@ -1945,11 +1945,11 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data, */ 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 */ @@ -1974,10 +1974,10 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data, 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 */ diff --git a/lib/hostasyn.c b/lib/hostasyn.c index 56a6fc2b72..b25de1d417 100644 --- a/lib/hostasyn.c +++ b/lib/hostasyn.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -66,25 +66,23 @@ * * 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); @@ -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- 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 */ @@ -117,12 +115,12 @@ CURLcode Curl_addrinfo_callback(struct connectdata *conn, * 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 */ diff --git a/lib/hostip.c b/lib/hostip.c index a3f6090ab8..9ca9bdbe71 100644 --- a/lib/hostip.c +++ b/lib/hostip.c @@ -253,14 +253,12 @@ sigjmp_buf curl_jmpenv; #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 */ @@ -321,7 +319,7 @@ Curl_fetch_addr(struct connectdata *conn, 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! */ @@ -480,16 +478,16 @@ Curl_cache_addr(struct Curl_easy *data, * 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 */ @@ -497,7 +495,7 @@ enum resolve_t Curl_resolv(struct connectdata *conn, 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); @@ -523,7 +521,7 @@ enum resolve_t Curl_resolv(struct connectdata *conn, 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) @@ -569,13 +567,13 @@ enum resolve_t Curl_resolv(struct connectdata *conn, 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], @@ -589,7 +587,7 @@ enum resolve_t Curl_resolv(struct connectdata *conn, /* 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) @@ -658,7 +656,7 @@ RETSIGTYPE alarmfunc(int sig) * 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, @@ -676,7 +674,6 @@ enum resolve_t Curl_resolv_timeout(struct connectdata *conn, #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; @@ -695,7 +692,7 @@ enum resolve_t Curl_resolv_timeout(struct connectdata *conn, 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 @@ -748,7 +745,7 @@ enum resolve_t Curl_resolv_timeout(struct connectdata *conn, #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 @@ -757,7 +754,7 @@ enum resolve_t Curl_resolv_timeout(struct connectdata *conn, /* 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: @@ -784,7 +781,7 @@ 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); @@ -1068,29 +1065,29 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data) 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 @@ -1101,21 +1098,19 @@ int Curl_resolv_getsock(struct connectdata *conn, 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); diff --git a/lib/hostip.h b/lib/hostip.h index 60e0b7795b..6deeb9f9cb 100644 --- a/lib/hostip.h +++ b/lib/hostip.h @@ -85,12 +85,12 @@ enum resolve_t { 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); @@ -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 * 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); @@ -148,7 +148,7 @@ int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa, /* 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. @@ -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 * 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); @@ -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. */ 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 */ diff --git a/lib/hostip4.c b/lib/hostip4.c index f1acb90939..d0754af223 100644 --- a/lib/hostip4.c +++ b/lib/hostip4.c @@ -89,7 +89,7 @@ bool Curl_ipvalid(struct Curl_easy *data, struct connectdata *conn) * 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) @@ -97,14 +97,14 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, 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; } diff --git a/lib/hostip6.c b/lib/hostip6.c index f9dd627ee4..53b3c67223 100644 --- a/lib/hostip6.c +++ b/lib/hostip6.c @@ -127,7 +127,7 @@ static void dump_addrinfo(struct connectdata *conn, * 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) @@ -141,14 +141,11 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, 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; @@ -166,7 +163,7 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, 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 diff --git a/lib/multi.c b/lib/multi.c index 34c916e336..0f9d79dc2d 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -565,7 +565,7 @@ static CURLcode multi_done(struct Curl_easy *data, 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); @@ -995,7 +995,7 @@ static int multi_getsock(struct Curl_easy *data, 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: @@ -1733,15 +1733,15 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, 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 @@ -1754,7 +1754,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, 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 diff --git a/lib/socks.c b/lib/socks.c index 9252e2c174..165c5496f5 100644 --- a/lib/socks.c +++ b/lib/socks.c @@ -238,7 +238,7 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user, /* 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; @@ -261,14 +261,14 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user, 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; @@ -754,7 +754,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user, 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) @@ -775,14 +775,14 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user, 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; diff --git a/lib/url.c b/lib/url.c index fe6c9a1f27..38f51e8a34 100644 --- a/lib/url.c +++ b/lib/url.c @@ -427,7 +427,7 @@ CURLcode Curl_close(struct Curl_easy **datap) 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); @@ -643,7 +643,7 @@ CURLcode Curl_open(struct Curl_easy **curl) 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); @@ -664,7 +664,7 @@ CURLcode Curl_open(struct Curl_easy **curl) } 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); @@ -722,7 +722,7 @@ static void conn_shutdown(struct Curl_easy *data, struct connectdata *conn) 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 */ @@ -3307,7 +3307,7 @@ static CURLcode resolve_server(struct Curl_easy *data, 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; @@ -3332,7 +3332,7 @@ static CURLcode resolve_server(struct Curl_easy *data, 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) diff --git a/lib/urldata.h b/lib/urldata.h index 5f3b7e7ec6..95ef175a12 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -539,15 +539,21 @@ struct hostname { #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 @@ -1093,9 +1099,6 @@ struct connectdata { 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; @@ -1330,7 +1333,6 @@ struct urlpieces { 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 */ @@ -1365,8 +1367,9 @@ struct UrlState { 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 */ diff --git a/tests/data/test1082 b/tests/data/test1082 index 0df70afaed..6791a6b10b 100644 --- a/tests/data/test1082 +++ b/tests/data/test1082 @@ -32,7 +32,7 @@ http HTTP GET with localhost --interface -http://%HOSTIP:%HTTPPORT/1082 --interface localhost +http://%HOSTIP:%HTTPPORT/1082 -4 --interface localhost perl -e "print 'Test requires default test client host address' if ( '%CLIENTIP' ne '127.0.0.1' );"