mirror of
https://github.com/curl/curl.git
synced 2026-08-24 21:43:32 +03:00
asyn-thread: use c-ares to resolve HTTPS RR
Allow building with c-ares and yet use threaded resolver for the main host A/AAAA resolving: `--with-ares` provides the c-ares install path and defaults to use c-ares for name resolving `--with-threaded-resolver` still uses c-ares in the build (for HTTPS) but uses the threaded resolver for "normal" resolves. It works similarly for cmake: ENABLE_ARES enables ares, and if ENABLE_THREADED_RESOLVER also is set, c-ares is used for HTTPS RR and the threaded resolver for "normal" resolves. HTTPSRR and c-ares-rr are new features return by curl_version_info() and thus shown by curl -V. The c-ares-rr feature bit is there to make it possible to distinguish between builds using c-ares for all name resolves and builds that use the threaded resolves for the regular name resolves and c-ares for HTTPSRR only. "c-ares-rr" means it does not use c-ares for "plain" name resolves. HTTPSRR support is EXPERIMENTAL only. Closes #16054
This commit is contained in:
parent
520e67dd39
commit
0d4fdbf15d
18 changed files with 470 additions and 421 deletions
|
|
@ -64,6 +64,14 @@
|
|||
#include "inet_ntop.h"
|
||||
#include "curl_threads.h"
|
||||
#include "connect.h"
|
||||
|
||||
#ifdef USE_ARES
|
||||
#include <ares.h>
|
||||
#ifdef USE_HTTPSRR
|
||||
#define USE_HTTPSRR_ARES 1 /* the combo */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
|
|
@ -145,32 +153,6 @@ static bool init_resolve_thread(struct Curl_easy *data,
|
|||
const struct addrinfo *hints);
|
||||
|
||||
|
||||
/* Data for synchronization between resolver thread and its parent */
|
||||
struct thread_sync_data {
|
||||
curl_mutex_t *mtx;
|
||||
int done;
|
||||
int port;
|
||||
char *hostname; /* hostname to resolve, Curl_async.hostname
|
||||
duplicate */
|
||||
#ifndef CURL_DISABLE_SOCKETPAIR
|
||||
struct Curl_easy *data;
|
||||
curl_socket_t sock_pair[2]; /* eventfd/pipes/socket pair */
|
||||
#endif
|
||||
int sock_error;
|
||||
struct Curl_addrinfo *res;
|
||||
#ifdef HAVE_GETADDRINFO
|
||||
struct addrinfo hints;
|
||||
#endif
|
||||
struct thread_data *td; /* for thread-self cleanup */
|
||||
};
|
||||
|
||||
struct thread_data {
|
||||
curl_thread_t thread_hnd;
|
||||
unsigned int poll_interval;
|
||||
timediff_t interval_end;
|
||||
struct thread_sync_data tsd;
|
||||
};
|
||||
|
||||
static struct thread_sync_data *conn_thread_sync_data(struct Curl_easy *data)
|
||||
{
|
||||
return &(data->state.async.tdata->tsd);
|
||||
|
|
@ -220,7 +202,7 @@ int init_thread_sync_data(struct thread_data *td,
|
|||
/* Treat the request as done until the thread actually starts so any early
|
||||
* cleanup gets done properly.
|
||||
*/
|
||||
tsd->done = 1;
|
||||
tsd->done = TRUE;
|
||||
#ifdef HAVE_GETADDRINFO
|
||||
DEBUGASSERT(hints);
|
||||
tsd->hints = *hints;
|
||||
|
|
@ -343,7 +325,7 @@ CURL_STDCALL getaddrinfo_thread(void *arg)
|
|||
}
|
||||
}
|
||||
#endif
|
||||
tsd->done = 1;
|
||||
tsd->done = TRUE;
|
||||
Curl_mutex_release(tsd->mtx);
|
||||
}
|
||||
|
||||
|
|
@ -382,7 +364,7 @@ CURL_STDCALL gethostbyname_thread(void *arg)
|
|||
free(td);
|
||||
}
|
||||
else {
|
||||
tsd->done = 1;
|
||||
tsd->done = TRUE;
|
||||
Curl_mutex_release(tsd->mtx);
|
||||
}
|
||||
|
||||
|
|
@ -398,19 +380,22 @@ static void destroy_async_data(struct Curl_async *async)
|
|||
{
|
||||
if(async->tdata) {
|
||||
struct thread_data *td = async->tdata;
|
||||
int done;
|
||||
bool done;
|
||||
#ifndef CURL_DISABLE_SOCKETPAIR
|
||||
curl_socket_t sock_rd = td->tsd.sock_pair[0];
|
||||
struct Curl_easy *data = td->tsd.data;
|
||||
#endif
|
||||
|
||||
#ifdef USE_HTTPSRR_ARES
|
||||
ares_destroy(data->state.async.tdata->channel);
|
||||
#endif
|
||||
/*
|
||||
* if the thread is still blocking in the resolve syscall, detach it and
|
||||
* let the thread do the cleanup...
|
||||
*/
|
||||
Curl_mutex_acquire(td->tsd.mtx);
|
||||
done = td->tsd.done;
|
||||
td->tsd.done = 1;
|
||||
td->tsd.done = TRUE;
|
||||
Curl_mutex_release(td->tsd.mtx);
|
||||
|
||||
if(!done) {
|
||||
|
|
@ -439,6 +424,24 @@ static void destroy_async_data(struct Curl_async *async)
|
|||
async->hostname = NULL;
|
||||
}
|
||||
|
||||
#ifdef USE_HTTPSRR_ARES
|
||||
static CURLcode resolve_httpsrr(struct Curl_easy *data,
|
||||
struct Curl_async *asp)
|
||||
{
|
||||
int status = ares_init(&asp->tdata->channel);
|
||||
if(status != ARES_SUCCESS)
|
||||
return CURLE_FAILED_INIT;
|
||||
|
||||
memset(&asp->tdata->hinfo, 0, sizeof(struct Curl_https_rrinfo));
|
||||
ares_query_dnsrec(asp->tdata->channel,
|
||||
asp->hostname, ARES_CLASS_IN,
|
||||
ARES_REC_TYPE_HTTPS,
|
||||
Curl_dnsrec_done_cb, data, NULL);
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* init_resolve_thread() starts a new thread that performs the actual
|
||||
* resolve. This function returns before the resolve is done.
|
||||
|
|
@ -474,8 +477,8 @@ static bool init_resolve_thread(struct Curl_easy *data,
|
|||
if(!asp->hostname)
|
||||
goto err_exit;
|
||||
|
||||
/* The thread will set this to 1 when complete. */
|
||||
td->tsd.done = 0;
|
||||
/* The thread will set this TRUE when complete. */
|
||||
td->tsd.done = FALSE;
|
||||
|
||||
#ifdef HAVE_GETADDRINFO
|
||||
td->thread_hnd = Curl_thread_create(getaddrinfo_thread, &td->tsd);
|
||||
|
|
@ -485,11 +488,14 @@ static bool init_resolve_thread(struct Curl_easy *data,
|
|||
|
||||
if(td->thread_hnd == curl_thread_t_null) {
|
||||
/* The thread never started, so mark it as done here for proper cleanup. */
|
||||
td->tsd.done = 1;
|
||||
td->tsd.done = TRUE;
|
||||
err = errno;
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
#ifdef USE_HTTPSRR_ARES
|
||||
if(resolve_httpsrr(data, asp))
|
||||
goto err_exit;
|
||||
#endif
|
||||
return TRUE;
|
||||
|
||||
err_exit:
|
||||
|
|
@ -587,7 +593,7 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
|
|||
struct Curl_dns_entry **entry)
|
||||
{
|
||||
struct thread_data *td = data->state.async.tdata;
|
||||
int done = 0;
|
||||
bool done = FALSE;
|
||||
|
||||
DEBUGASSERT(entry);
|
||||
*entry = NULL;
|
||||
|
|
@ -596,6 +602,10 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
|
|||
DEBUGASSERT(td);
|
||||
return CURLE_COULDNT_RESOLVE_HOST;
|
||||
}
|
||||
#ifdef USE_HTTPSRR_ARES
|
||||
if(Curl_ares_perform(data->state.async.tdata->channel, 0) < 0)
|
||||
return CURLE_UNRECOVERABLE_POLL;
|
||||
#endif
|
||||
|
||||
Curl_mutex_acquire(td->tsd.mtx);
|
||||
done = td->tsd.done;
|
||||
|
|
@ -643,18 +653,28 @@ int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *socks)
|
|||
timediff_t milli;
|
||||
timediff_t ms;
|
||||
struct resdata *reslv = (struct resdata *)data->state.async.resolver;
|
||||
int socketi = 0;
|
||||
#ifndef CURL_DISABLE_SOCKETPAIR
|
||||
struct thread_data *td = data->state.async.tdata;
|
||||
#else
|
||||
(void)socks;
|
||||
#endif
|
||||
|
||||
#ifdef USE_HTTPSRR_ARES
|
||||
if(data->state.async.tdata) {
|
||||
ret_val = Curl_ares_getsock(data, data->state.async.tdata->channel, socks);
|
||||
for(socketi = 0; socketi < (MAX_SOCKSPEREASYHANDLE - 1); socketi++)
|
||||
if(!ARES_GETSOCK_READABLE(ret_val, socketi) &&
|
||||
!ARES_GETSOCK_WRITABLE(ret_val, socketi))
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifndef CURL_DISABLE_SOCKETPAIR
|
||||
if(td) {
|
||||
/* return read fd to client for polling the DNS resolution status */
|
||||
socks[0] = td->tsd.sock_pair[0];
|
||||
socks[socketi] = td->tsd.sock_pair[0];
|
||||
td->tsd.data = data;
|
||||
ret_val = GETSOCK_READSOCK(0);
|
||||
ret_val = GETSOCK_READSOCK(socketi);
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue