hostip: remove conn->data from resolver functions

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

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

View file

@ -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;
}