summaryrefslogtreecommitdiff
path: root/libs/libcurl/src/asyn-thread.c
diff options
context:
space:
mode:
Diffstat (limited to 'libs/libcurl/src/asyn-thread.c')
-rw-r--r--libs/libcurl/src/asyn-thread.c148
1 files changed, 72 insertions, 76 deletions
diff --git a/libs/libcurl/src/asyn-thread.c b/libs/libcurl/src/asyn-thread.c
index 7c85982748..9fcbc3c1fd 100644
--- a/libs/libcurl/src/asyn-thread.c
+++ b/libs/libcurl/src/asyn-thread.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -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);
@@ -160,12 +160,11 @@ static bool init_resolve_thread(struct connectdata *conn,
struct thread_sync_data {
curl_mutex_t *mtx;
int done;
-
+ int port;
char *hostname; /* hostname to resolve, Curl_async.hostname
duplicate */
- int port;
#ifdef USE_SOCKETPAIR
- struct connectdata *conn;
+ struct Curl_easy *data;
curl_socket_t sock_pair[2]; /* socket pair */
#endif
int sock_error;
@@ -183,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 */
@@ -269,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.
*/
@@ -385,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
/*
@@ -413,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
}
@@ -430,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. */
@@ -477,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;
@@ -489,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;
@@ -506,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;
}
@@ -515,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;
}
@@ -555,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);
}
/*
@@ -581,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);
}
/*
@@ -592,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);
@@ -612,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 */
@@ -641,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
@@ -665,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 {
@@ -693,25 +691,24 @@ 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;
+ struct resdata *reslv = (struct resdata *)data->state.async.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;
}
- failf(conn->data, "getaddrinfo() thread failed\n");
+ failf(data, "getaddrinfo() thread failed");
return NULL;
}
@@ -721,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 */
@@ -737,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;
@@ -749,24 +745,24 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
break;
}
- if((pf != PF_INET) && !Curl_ipv6works(conn))
+ if((pf != PF_INET) && !Curl_ipv6works(data))
/* The stack seems to be a non-IPv6 one */
pf = PF_INET;
#endif /* CURLRES_IPV6 */
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;
}
- failf(data, "getaddrinfo() thread failed to start\n");
+ failf(data, "getaddrinfo() thread failed to start");
return NULL;
}