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:
Daniel Stenberg 2025-01-21 11:42:20 +01:00
parent 520e67dd39
commit 0d4fdbf15d
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
18 changed files with 470 additions and 421 deletions

View File

@ -346,6 +346,7 @@ httpget
HttpGet
HTTPS
https
HTTPSRR
hyper's
Högskolan
IANA
@ -779,10 +780,10 @@ src
SRP
SRWLOCK
SSL
SSLS
ssl
SSLeay
SSLKEYLOGFILE
SSLS
sslv
SSLv
SSLVERSION

View File

@ -243,9 +243,15 @@ elseif(DOS OR AMIGA)
endif()
option(CURL_LTO "Enable compiler Link Time Optimizations" OFF)
cmake_dependent_option(ENABLE_THREADED_RESOLVER "Enable threaded DNS lookup"
ON "NOT ENABLE_ARES;NOT DOS;NOT AMIGA"
OFF)
if(NOT DOS AND NOT AMIGA)
# if c-ares is used, default the threaded resolver to OFF
if(ENABLE_ARES)
set(_enable_threaded_resolver_default OFF)
else()
set(_enable_threaded_resolver_default ON)
endif()
option(ENABLE_THREADED_RESOLVER "Enable threaded DNS lookup" ${_enable_threaded_resolver_default})
endif()
include(PickyWarnings)
@ -1003,7 +1009,10 @@ if(USE_ECH)
if(NOT HAVE_ECH)
message(FATAL_ERROR "ECH support missing in OpenSSL/BoringSSL/AWS-LC/wolfSSL")
else()
message(STATUS "ECH enabled.")
message(STATUS "ECH enabled")
# ECH wants HTTPSRR
set(USE_HTTPSRR ON)
message(STATUS "HTTPSRR enabled")
endif()
else()
message(FATAL_ERROR "ECH requires ECH-enablded OpenSSL, BoringSSL, AWS-LC or wolfSSL")
@ -2098,6 +2107,7 @@ curl_add_if("brotli" HAVE_BROTLI)
curl_add_if("gsasl" USE_GSASL)
curl_add_if("zstd" HAVE_ZSTD)
curl_add_if("AsynchDNS" USE_ARES OR USE_THREADS_POSIX OR USE_THREADS_WIN32)
curl_add_if("c-ares-rr" USE_ARES AND ENABLE_THREADED_RESOLVER)
curl_add_if("IDN" (HAVE_LIBIDN2 AND HAVE_IDN2_H) OR
USE_WIN32_IDN OR
USE_APPLE_IDN)
@ -2128,6 +2138,7 @@ curl_add_if("threadsafe" HAVE_ATOMIC OR
curl_add_if("Debug" ENABLE_DEBUG)
curl_add_if("TrackMemory" ENABLE_CURLDEBUG)
curl_add_if("ECH" _ssl_enabled AND HAVE_ECH)
curl_add_if("HTTPSRR" _ssl_enabled AND USE_HTTPSRR)
curl_add_if("PSL" USE_LIBPSL)
curl_add_if("CAcert" CURL_CA_EMBED_SET)
curl_add_if("SSLS-EXPORT" _ssl_enabled AND USE_SSLS_EXPORT)

View File

@ -4134,74 +4134,26 @@ dnl set variable for use in automakefile(s)
AM_CONDITIONAL(USE_MANUAL, test x"$USE_MANUAL" = x1)
CURL_CHECK_LIB_ARES
CURL_CHECK_OPTION_THREADED_RESOLVER
if test "x$want_ares" != xyes; then
CURL_CHECK_OPTION_THREADED_RESOLVER
if test "$ipv6" = yes; then
CURL_DARWIN_SYSTEMCONFIGURATION
fi
if test "$ipv6" = yes; then
CURL_DARWIN_SYSTEMCONFIGURATION
fi
dnl ************************************************************
dnl disable POSIX threads
dnl
AC_MSG_CHECKING([whether to use POSIX threads for threaded resolver])
AC_ARG_ENABLE(pthreads,
AS_HELP_STRING([--enable-pthreads],
[Enable POSIX threads (default for threaded resolver)])
AS_HELP_STRING([--disable-pthreads],[Disable POSIX threads]),
[ case "$enableval" in
no)
AC_MSG_RESULT(no)
want_pthreads=no
;;
*)
AC_MSG_RESULT(yes)
want_pthreads=yes
;;
esac ], [
default_pthreads=1
if test "$curl_cv_native_windows" = "yes"; then
default_pthreads=0
else
case $host_os in
msdos*)
default_pthreads=0
;;
esac
fi
if test "$default_pthreads" = '0'; then
AC_MSG_RESULT(no)
want_pthreads=no
else
AC_MSG_RESULT(auto)
want_pthreads=auto
fi
]
)
dnl turn off pthreads if rt is disabled
if test "$want_pthreads" != "no"; then
if test "$want_pthreads" = "yes" && test "$dontwant_rt" = "yes"; then
AC_MSG_ERROR([options --enable-pthreads and --disable-rt are mutually exclusive])
fi
if test "$dontwant_rt" != "no"; then
dnl if --enable-pthreads was explicit then warn it's being ignored
if test "$want_pthreads" = "yes"; then
AC_MSG_WARN([--enable-pthreads Ignored since librt is disabled.])
fi
want_pthreads=no
fi
if test "$want_threaded_resolver" = "yes" && test "$dontwant_rt" = "yes"; then
AC_MSG_ERROR([options --enable-pthreads and --disable-rt are mutually exclusive])
fi
dnl turn off pthreads if no threaded resolver
if test "$want_pthreads" != "no" && test "$want_thres" != "yes"; then
want_pthreads=no
dnl Windows threaded resolver check
if test "$want_threaded_resolver" = "yes" && test "$curl_cv_native_windows" = "yes"; then
USE_THREADS_WIN32=1
AC_DEFINE(USE_THREADS_WIN32, 1, [if you want Win32 threaded DNS lookup])
curl_res_msg="Win32 threaded"
fi
dnl detect pthreads
if test "$want_pthreads" != "no"; then
if test "$want_threaded_resolver" = "yes" && test "$USE_THREADS_WIN32" != "1"; then
AC_CHECK_HEADER(pthread.h,
[ AC_DEFINE(HAVE_PTHREAD_H, 1, [if you have <pthread.h>])
save_CFLAGS="$CFLAGS"
@ -4262,19 +4214,9 @@ if test "$want_pthreads" != "no"; then
])
fi
dnl threaded resolver check
if test "$want_thres" = "yes" && test "x$USE_THREADS_POSIX" != "x1"; then
if test "$want_pthreads" = "yes"; then
AC_MSG_ERROR([--enable-pthreads but pthreads was not found])
fi
dnl If native Windows fallback on Win32 threads since no POSIX threads
if test "$curl_cv_native_windows" = "yes"; then
USE_THREADS_WIN32=1
AC_DEFINE(USE_THREADS_WIN32, 1, [if you want Win32 threaded DNS lookup])
curl_res_msg="Win32 threaded"
else
AC_MSG_ERROR([Threaded resolver enabled but no thread library found])
fi
dnl Did we find a threading option?
if test "$want_threaded_resolver" != "no" -a "x$USE_THREADS_POSIX" != "x1" -a "x$USE_THREADS_WIN32" != "x1"; then
AC_MSG_ERROR([Threaded resolver enabled but no thread library found])
fi
AC_CHECK_HEADER(dirent.h,
@ -4873,15 +4815,6 @@ if test "x$hsts" != "xyes"; then
fi
dnl *************************************************************
dnl check whether HTTPSRR support if desired
dnl
if test "x$want_httpsrr" != "xno"; then
AC_MSG_RESULT([HTTPSRR support is available])
AC_DEFINE(USE_HTTPSRR, 1, [enable HTTPS RR support])
experimental="$experimental HTTPSRR"
fi
dnl *************************************************************
dnl check whether ECH support, if desired, is actually available
dnl
@ -4909,11 +4842,24 @@ if test "x$want_ech" != "xno"; then
AC_DEFINE(USE_ECH, 1, [if ECH support is available])
AC_MSG_RESULT($ECH_SUPPORT)
experimental="$experimental ECH"
dnl ECH wants HTTPSRR
want_httpsrr="yes"
else
AC_MSG_ERROR([--enable-ech ignored: No ECH support found])
fi
fi
dnl *************************************************************
dnl check whether HTTPSRR support if desired
dnl
if test "x$want_httpsrr" != "xno"; then
AC_MSG_RESULT([HTTPSRR support is enabled])
AC_DEFINE(USE_HTTPSRR, 1, [enable HTTPS RR support])
experimental="$experimental HTTPSRR"
curl_httpsrr_msg="enabled (--disable-httpsrr)"
fi
dnl *************************************************************
dnl check whether OpenSSL (lookalikes) have SSL_set0_wbio
dnl
@ -5071,6 +5017,9 @@ if test "x$USE_ARES" = "x1" -o "x$USE_THREADS_POSIX" = "x1" \
-o "x$USE_THREADS_WIN32" = "x1"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES AsynchDNS"
fi
if test "x$USE_ARES" = "x1" -a "$want_threaded_resolver" = "yes"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES c-ares-rr"
fi
if test "x$IDN_ENABLED" = "x1"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES IDN"
fi
@ -5177,6 +5126,10 @@ if test "x$OPENSSL_ENABLED" = "x1" -o -n "$SSL_ENABLED"; then
fi
fi
if test "x$want_httpsrr" != "xno"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES HTTPSRR"
fi
if test "x$SSLS_EXPORT_ENABLED" = "x1"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES SSLS-EXPORT"
fi
@ -5446,6 +5399,7 @@ AC_MSG_NOTICE([Configured to build curl/libcurl:
HTTP2: ${curl_h2_msg}
HTTP3: ${curl_h3_msg}
ECH: ${curl_ech_msg}
HTTPS RR: ${curl_httpsrr_msg}
SSLS-EXPORT: ${curl_ssls_export_msg}
Protocols: ${SUPPORT_PROTOCOLS_LOWER}
Features: ${SUPPORT_FEATURES}

View File

@ -151,13 +151,13 @@ entry.
# FEATURES
## alt-svc
## `alt-svc`
*features* mask bit: CURL_VERSION_ALTSVC
HTTP Alt-Svc parsing and the associated options (Added in 7.64.1)
## AsynchDNS
## `AsynchDNS`
*features* mask bit: CURL_VERSION_ASYNCHDNS
@ -165,32 +165,40 @@ libcurl was built with support for asynchronous name lookups, which allows
more exact timeouts (even on Windows) and less blocking when using the multi
interface. (added in 7.10.7)
## brotli
## `brotli`
*features* mask bit: CURL_VERSION_BROTLI
supports HTTP Brotli content encoding using libbrotlidec (Added in 7.57.0)
## Debug
## `c-ares-rr`
*features* mask bit: non-existent
libcurl was built to use c-ares for EXPERIMENTAL HTTPS resource record
resolves, but uses the threaded resolver for "normal" resolves (Added in
8.12.0)
## `Debug`
*features* mask bit: CURL_VERSION_DEBUG
libcurl was built with debug capabilities (added in 7.10.6)
## ECH
## `ECH`
*features* mask bit: non-existent
libcurl was built with ECH support (experimental, added in 8.8.0)
## gsasl
## `gsasl`
*features* mask bit: CURL_VERSION_GSASL
libcurl was built with libgsasl and thus with some extra SCRAM-SHA
authentication methods. (added in 7.76.0)
## GSS-API
## `GSS-API`
*features* mask bit: CURL_VERSION_GSSAPI
@ -199,66 +207,73 @@ functions for Kerberos and SPNEGO authentication. It also allows libcurl
to use the current user credentials without the app having to pass them on.
(Added in 7.38.0)
## HSTS
## `HSTS`
*features* mask bit: CURL_VERSION_HSTS
libcurl was built with support for HSTS (HTTP Strict Transport Security)
(Added in 7.74.0)
## HTTP2
## `HTTP2`
*features* mask bit: CURL_VERSION_HTTP2
libcurl was built with support for HTTP2.
(Added in 7.33.0)
## HTTP3
## `HTTP3`
*features* mask bit: CURL_VERSION_HTTP3
HTTP/3 and QUIC support are built-in (Added in 7.66.0)
## HTTPS-proxy
## `HTTPS-proxy`
*features* mask bit: CURL_VERSION_HTTPS_PROXY
libcurl was built with support for HTTPS-proxy.
(Added in 7.52.0)
## IDN
## `HTTPSRR`
*features* mask bit: non-existent
libcurl was built with EXPERIMENTAL support for HTTPS resource records (Added
in 8.12.0)
## `IDN`
*features* mask bit: CURL_VERSION_IDN
libcurl was built with support for IDNA, domain names with international
letters. (Added in 7.12.0)
## IPv6
## `IPv6`
*features* mask bit: CURL_VERSION_IPV6
supports IPv6
## Kerberos
## `Kerberos`
*features* mask bit: CURL_VERSION_KERBEROS5
supports Kerberos V5 authentication for FTP, IMAP, LDAP, POP3, SMTP and
SOCKSv5 proxy. (Added in 7.40.0)
## Largefile
## `Largefile`
*features* mask bit: CURL_VERSION_LARGEFILE
libcurl was built with support for large files. (Added in 7.11.1)
## libz
## `libz`
*features* mask bit: CURL_VERSION_LIBZ
supports HTTP deflate using libz (Added in 7.10)
## MultiSSL
## `MultiSSL`
*features* mask bit: CURL_VERSION_MULTI_SSL
@ -266,20 +281,20 @@ libcurl was built with multiple SSL backends. For details, see
curl_global_sslset(3).
(Added in 7.56.0)
## NTLM
## `NTLM`
*features* mask bit: CURL_VERSION_NTLM
supports HTTP NTLM (added in 7.10.6)
## NTLM_WB
## `NTLM_WB`
*features* mask bit: CURL_VERSION_NTLM_WB
libcurl was built with support for NTLM delegation to a winbind helper.
(Added in 7.22.0) This feature was removed from curl in 8.8.0.
## PSL
## `PSL`
*features* mask bit: CURL_VERSION_PSL
@ -287,27 +302,27 @@ libcurl was built with support for Mozilla's Public Suffix List. This makes
libcurl ignore cookies with a domain that is on the list.
(Added in 7.47.0)
## SPNEGO
## `SPNEGO`
*features* mask bit: CURL_VERSION_SPNEGO
libcurl was built with support for SPNEGO authentication (Simple and Protected
GSS-API Negotiation Mechanism, defined in RFC 2478.) (added in 7.10.8)
## SSL
## `SSL`
*features* mask bit: CURL_VERSION_SSL
supports SSL (HTTPS/FTPS) (Added in 7.10)
## SSLS-EXPORT
## `SSLS-EXPORT`
*features* mask bit: non-existent
libcurl was built with SSL session import/export support
(experimental, added in 8.12.0)
## SSPI
## `SSPI`
*features* mask bit: CURL_VERSION_SSPI
@ -316,42 +331,42 @@ makes libcurl use Windows-provided functions for Kerberos, NTLM, SPNEGO and
Digest authentication. It also allows libcurl to use the current user
credentials without the app having to pass them on. (Added in 7.13.2)
## threadsafe
## `threadsafe`
*features* mask bit: CURL_VERSION_THREADSAFE
libcurl was built with thread-safety support (Atomic or SRWLOCK) to protect
curl initialization. (Added in 7.84.0) See libcurl-thread(3)
## TLS-SRP
## `TLS-SRP`
*features* mask bit: CURL_VERSION_TLSAUTH_SRP
libcurl was built with support for TLS-SRP (in one or more of the built-in TLS
backends). (Added in 7.21.4)
## TrackMemory
## `TrackMemory`
*features* mask bit: CURL_VERSION_CURLDEBUG
libcurl was built with memory tracking debug capabilities. This is mainly of
interest for libcurl hackers. (added in 7.19.6)
## Unicode
## `Unicode`
*features* mask bit: CURL_VERSION_UNICODE
libcurl was built with Unicode support on Windows. This makes non-ASCII
characters work in filenames and options passed to libcurl. (Added in 7.72.0)
## UnixSockets
## `UnixSockets`
*features* mask bit: CURL_VERSION_UNIX_SOCKETS
libcurl was built with support for Unix domain sockets.
(Added in 7.40.0)
## zstd
## `zstd`
*features* mask bit: CURL_VERSION_ZSTD

View File

@ -24,14 +24,14 @@
#include "curl_setup.h"
#ifdef USE_ARES
/***********************************************************************
* Only for ares-enabled builds
* And only for functions that fulfill the asynch resolver backend API
* as defined in asyn.h, nothing else belongs in this file!
**********************************************************************/
#ifdef CURLRES_ARES
#include <limits.h>
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
@ -70,6 +70,94 @@
#include <ares_version.h> /* really old c-ares did not include this by
itself */
/*
* Curl_ares_getsock() is called when the outside world (using
* curl_multi_fdset()) wants to get our fd_set setup and we are talking with
* ares. The caller must make sure that this function is only called when we
* have a working ares channel.
*
* Returns: sockets-in-use-bitmap
*/
int Curl_ares_getsock(struct Curl_easy *data,
ares_channel channel,
curl_socket_t *socks)
{
struct timeval maxtime = { CURL_TIMEOUT_RESOLVE, 0 };
struct timeval timebuf;
int max = ares_getsock(channel,
(ares_socket_t *)socks, MAX_SOCKSPEREASYHANDLE);
struct timeval *timeout = ares_timeout(channel, &maxtime, &timebuf);
timediff_t milli = curlx_tvtoms(timeout);
Curl_expire(data, milli, EXPIRE_ASYNC_NAME);
return max;
}
/*
* Curl_ares_perform()
*
* 1) Ask ares what sockets it currently plays with, then
* 2) wait for the timeout period to check for action on ares' sockets.
* 3) tell ares to act on all the sockets marked as "with action"
*
* return number of sockets it worked on, or -1 on error
*/
int Curl_ares_perform(ares_channel channel,
timediff_t timeout_ms)
{
int nfds;
int bitmask;
ares_socket_t socks[ARES_GETSOCK_MAXNUM];
struct pollfd pfd[ARES_GETSOCK_MAXNUM];
int i;
int num = 0;
bitmask = ares_getsock(channel, socks, ARES_GETSOCK_MAXNUM);
for(i = 0; i < ARES_GETSOCK_MAXNUM; i++) {
pfd[i].events = 0;
pfd[i].revents = 0;
if(ARES_GETSOCK_READABLE(bitmask, i)) {
pfd[i].fd = socks[i];
pfd[i].events |= POLLRDNORM|POLLIN;
}
if(ARES_GETSOCK_WRITABLE(bitmask, i)) {
pfd[i].fd = socks[i];
pfd[i].events |= POLLWRNORM|POLLOUT;
}
if(pfd[i].events)
num++;
else
break;
}
if(num) {
nfds = Curl_poll(pfd, (unsigned int)num, timeout_ms);
if(nfds < 0)
return -1;
}
else
nfds = 0;
if(!nfds)
/* Call ares_process() unconditionally here, even if we simply timed out
above, as otherwise the ares name resolve will not timeout! */
ares_process_fd(channel, 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(channel,
(pfd[i].revents & (POLLRDNORM|POLLIN)) ?
pfd[i].fd : ARES_SOCKET_BAD,
(pfd[i].revents & (POLLWRNORM|POLLOUT)) ?
pfd[i].fd : ARES_SOCKET_BAD);
}
return nfds;
}
#ifdef CURLRES_ARES
#if ARES_VERSION >= 0x010500
/* c-ares 1.5.0 or later, the callback proto is modified */
#define HAVE_CARES_CALLBACK_TIMEOUTS 1
@ -98,8 +186,9 @@
#if ARES_VERSION >= 0x011c00
/* 1.28.0 and later have ares_query_dnsrec */
#define HAVE_ARES_QUERY_DNSREC 1
#else
#undef USE_HTTPSRR
#ifdef USE_HTTPSRR
#define USE_HTTPSRR_ARES 1
#endif
#endif
/* The last 3 #include files should be in this order */
@ -107,20 +196,6 @@
#include "curl_memory.h"
#include "memdebug.h"
struct thread_data {
int num_pending; /* number of outstanding c-ares requests */
struct Curl_addrinfo *temp_ai; /* intermediary result while fetching c-ares
parts */
int last_status;
#ifndef HAVE_CARES_GETADDRINFO
struct curltime happy_eyeballs_dns_time; /* when this timer started, or 0 */
#endif
#ifdef USE_HTTPSRR
struct Curl_https_rrinfo hinfo;
#endif
char hostname[1];
};
/* How long we are willing to wait for additional parallel responses after
obtaining a "definitive" one. For old c-ares without getaddrinfo.
@ -292,89 +367,13 @@ static void destroy_async_data(struct Curl_async *async)
/*
* Curl_resolver_getsock() is called when someone from the outside world
* (using curl_multi_fdset()) wants to get our fd_set setup and we are talking
* with ares. The caller must make sure that this function is only called when
* we have a working ares channel.
*
* Returns: sockets-in-use-bitmap
* (using curl_multi_fdset()) wants to get our fd_set setup.
*/
int Curl_resolver_getsock(struct Curl_easy *data,
curl_socket_t *socks)
int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *socks)
{
struct timeval maxtime = { CURL_TIMEOUT_RESOLVE, 0 };
struct timeval timebuf;
int max = ares_getsock((ares_channel)data->state.async.resolver,
(ares_socket_t *)socks, MAX_SOCKSPEREASYHANDLE);
struct timeval *timeout =
ares_timeout((ares_channel)data->state.async.resolver, &maxtime, &timebuf);
timediff_t milli = curlx_tvtoms(timeout);
Curl_expire(data, milli, EXPIRE_ASYNC_NAME);
return max;
}
/*
* waitperform()
*
* 1) Ask ares what sockets it currently plays with, then
* 2) wait for the timeout period to check for action on ares' sockets.
* 3) tell ares to act on all the sockets marked as "with action"
*
* return number of sockets it worked on, or -1 on error
*/
static int waitperform(struct Curl_easy *data, timediff_t timeout_ms)
{
int nfds;
int bitmask;
ares_socket_t socks[ARES_GETSOCK_MAXNUM];
struct pollfd pfd[ARES_GETSOCK_MAXNUM];
int i;
int num = 0;
bitmask = ares_getsock((ares_channel)data->state.async.resolver, socks,
ARES_GETSOCK_MAXNUM);
for(i = 0; i < ARES_GETSOCK_MAXNUM; i++) {
pfd[i].events = 0;
pfd[i].revents = 0;
if(ARES_GETSOCK_READABLE(bitmask, i)) {
pfd[i].fd = socks[i];
pfd[i].events |= POLLRDNORM|POLLIN;
}
if(ARES_GETSOCK_WRITABLE(bitmask, i)) {
pfd[i].fd = socks[i];
pfd[i].events |= POLLWRNORM|POLLOUT;
}
if(pfd[i].events)
num++;
else
break;
}
if(num) {
nfds = Curl_poll(pfd, (unsigned int)num, timeout_ms);
if(nfds < 0)
return -1;
}
else
nfds = 0;
if(!nfds)
/* Call ares_process() unconditionally here, even if we simply timed out
above, as otherwise the ares name resolve will not timeout! */
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.async.resolver,
(pfd[i].revents & (POLLRDNORM|POLLIN)) ?
pfd[i].fd : ARES_SOCKET_BAD,
(pfd[i].revents & (POLLWRNORM|POLLOUT)) ?
pfd[i].fd : ARES_SOCKET_BAD);
}
return nfds;
return Curl_ares_getsock(data, (ares_channel)data->state.async.resolver,
socks);
}
/*
@ -393,7 +392,7 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
DEBUGASSERT(dns);
*dns = NULL;
if(waitperform(data, 0) < 0)
if(Curl_ares_perform((ares_channel)data->state.async.resolver, 0) < 0)
return CURLE_UNRECOVERABLE_POLL;
#ifndef HAVE_CARES_GETADDRINFO
@ -431,7 +430,7 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
result = Curl_resolver_error(data);
else {
*dns = data->state.async.dns;
#ifdef USE_HTTPSRR
#ifdef USE_HTTPSRR_ARES
{
struct Curl_https_rrinfo *lhrr =
Curl_memdup(&res->hinfo, sizeof(struct Curl_https_rrinfo));
@ -503,7 +502,8 @@ CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
else
timeout_ms = 1000;
if(waitperform(data, timeout_ms) < 0)
if(Curl_ares_perform((ares_channel)data->state.async.resolver,
timeout_ms) < 0)
return CURLE_UNRECOVERABLE_POLL;
result = Curl_resolver_is_resolved(data, entry);
@ -768,72 +768,6 @@ static void addrinfo_cb(void *arg, int status, int timeouts,
#endif
#ifdef USE_HTTPSRR
static void httpsrr_opt(struct Curl_easy *data,
const ares_dns_rr_t *rr,
ares_dns_rr_key_t key, size_t idx)
{
size_t len = 0;
const unsigned char *val = NULL;
unsigned short code;
struct thread_data *res = data->state.async.tdata;
code = ares_dns_rr_get_opt(rr, key, idx, &val, &len);
switch(code) {
case HTTPS_RR_CODE_ALPN: /* str_list */
Curl_httpsrr_decode_alpn(val, len, res->hinfo.alpns);
infof(data, "HTTPS RR ALPN: %u %u %u %u",
res->hinfo.alpns[0], res->hinfo.alpns[1], res->hinfo.alpns[2],
res->hinfo.alpns[3]);
break;
case HTTPS_RR_CODE_NO_DEF_ALPN:
infof(data, "HTTPS RR no-def-alpn");
break;
case HTTPS_RR_CODE_IPV4: /* addr4 list */
infof(data, "HTTPS RR IPv4");
break;
case HTTPS_RR_CODE_ECH:
infof(data, "HTTPS RR ECH");
break;
case HTTPS_RR_CODE_IPV6: /* addr6 list */
infof(data, "HTTPS RR IPv6");
break;
case HTTPS_RR_CODE_PORT:
infof(data, "HTTPS RR port");
break;
default:
infof(data, "HTTPS RR unknown code");
break;
}
}
static void dnsrec_done_cb(void *arg, ares_status_t status,
size_t timeouts,
const ares_dns_record_t *dnsrec)
{
struct Curl_easy *data = arg;
size_t i;
struct thread_data *res = data->state.async.tdata;
(void)timeouts;
res->num_pending--;
if((ARES_SUCCESS != status) || !dnsrec)
return;
for(i = 0; i < ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_ANSWER); i++) {
size_t opt;
const ares_dns_rr_t *rr =
ares_dns_record_rr_get_const(dnsrec, ARES_SECTION_ANSWER, i);
if(ares_dns_rr_get_type(rr) != ARES_REC_TYPE_HTTPS)
continue;
for(opt = 0; opt < ares_dns_rr_get_opt_cnt(rr, ARES_RR_HTTPS_PARAMS);
opt++)
httpsrr_opt(data, rr, ARES_RR_HTTPS_PARAMS, opt);
}
}
#endif
/*
* Curl_resolver_getaddrinfo() - when using ares
*
@ -916,14 +850,14 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
query_completed_cb, data);
}
#endif
#ifdef USE_HTTPSRR
#ifdef USE_HTTPSRR_ARES
{
res->num_pending++; /* one more */
memset(&res->hinfo, 0, sizeof(struct Curl_https_rrinfo));
ares_query_dnsrec((ares_channel)data->state.async.resolver,
hostname, ARES_CLASS_IN,
ARES_REC_TYPE_HTTPS,
dnsrec_done_cb, data, NULL);
Curl_dnsrec_done_cb, data, NULL);
}
#endif
*waitp = 1; /* expect asynchronous response */
@ -1058,3 +992,5 @@ CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data,
#endif
}
#endif /* CURLRES_ARES */
#endif /* USE_ARES */

View File

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

View File

@ -26,6 +26,7 @@
#include "curl_setup.h"
#include "curl_addrinfo.h"
#include "httpsrr.h"
struct addrinfo;
struct hostent;
@ -33,6 +34,69 @@ struct Curl_easy;
struct connectdata;
struct Curl_dns_entry;
#ifdef CURLRES_THREADED
#include "curl_threads.h"
/* Data for synchronization between resolver thread and its parent */
struct thread_sync_data {
curl_mutex_t *mtx;
bool 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;
#if defined(USE_HTTPSRR) && defined(USE_ARES)
struct Curl_https_rrinfo hinfo;
ares_channel channel;
#endif
};
#elif defined(CURLRES_ARES) /* CURLRES_THREADED */
struct thread_data {
int num_pending; /* number of outstanding c-ares requests */
struct Curl_addrinfo *temp_ai; /* intermediary result while fetching c-ares
parts */
int last_status;
#ifndef HAVE_CARES_GETADDRINFO
struct curltime happy_eyeballs_dns_time; /* when this timer started, or 0 */
#endif
#ifdef USE_HTTPSRR
struct Curl_https_rrinfo hinfo;
#endif
char hostname[1];
};
#endif /* CURLRES_ARES */
#ifdef USE_ARES
#include <ares.h>
/* for HTTPS RR purposes as well */
int Curl_ares_getsock(struct Curl_easy *data,
ares_channel channel,
curl_socket_t *socks);
int Curl_ares_perform(ares_channel channel,
timediff_t timeout_ms);
#endif
/*
* This header defines all functions in the internal asynch resolver interface.
* All asynch resolvers need to provide these functions.

View File

@ -282,14 +282,6 @@
# define CURL_DISABLE_HTTP_AUTH 1
#endif
/*
* ECH requires HTTPSRR.
*/
#if defined(USE_ECH) && !defined(USE_HTTPSRR)
# define USE_HTTPSRR
#endif
/* ================================================================ */
/* No system header file shall be included in this file before this */
/* point. */
@ -710,15 +702,15 @@
# define CURLRES_IPV4
#endif
#ifdef USE_ARES
#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
# define CURLRES_ASYNCH
# define CURLRES_THREADED
#elif defined(USE_ARES)
# define CURLRES_ASYNCH
# define CURLRES_ARES
/* now undef the stock libc functions just to avoid them being used */
# undef HAVE_GETADDRINFO
# undef HAVE_FREEADDRINFO
#elif defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
# define CURLRES_ASYNCH
# define CURLRES_THREADED
#else
# define CURLRES_SYNCH
#endif

View File

@ -29,6 +29,7 @@
#include "curl_addrinfo.h"
#include "timeval.h" /* for timediff_t */
#include "asyn.h"
#include "httpsrr.h"
#include <setjmp.h>
@ -69,31 +70,6 @@ enum alpnid {
*/
struct Curl_hash *Curl_global_host_cache_init(void);
#ifdef USE_HTTPSRR
#define CURL_MAXLEN_host_name 253
#define MAX_HTTPSRR_ALPNS 4
struct Curl_https_rrinfo {
/*
* Fields from HTTPS RR. The only mandatory fields are priority and target.
* See https://datatracker.ietf.org/doc/html/rfc9460#section-14.3.2
*/
char *target;
unsigned char *ipv4hints; /* keytag = 4 */
size_t ipv4hints_len;
unsigned char *echconfiglist; /* keytag = 5 */
size_t echconfiglist_len;
unsigned char *ipv6hints; /* keytag = 6 */
size_t ipv6hints_len;
unsigned char alpns[MAX_HTTPSRR_ALPNS]; /* keytag = 1 */
/* store parsed alpnid entries in the array, end with ALPN_none */
int port; /* -1 means not set */
uint16_t priority;
bool no_def_alpn; /* keytag = 2 */
};
#endif
struct Curl_dns_entry {
struct Curl_addrinfo *addr;
#ifdef USE_HTTPSRR

View File

@ -30,6 +30,12 @@
#include "curl_addrinfo.h"
#include "httpsrr.h"
#include "connect.h"
#include "sendf.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
CURLcode Curl_httpsrr_decode_alpn(const unsigned char *cp, size_t len,
unsigned char *alpns)
@ -85,4 +91,77 @@ err:
return CURLE_BAD_CONTENT_ENCODING;
}
#ifdef USE_ARES
static void httpsrr_opt(struct Curl_easy *data,
const ares_dns_rr_t *rr,
ares_dns_rr_key_t key, size_t idx)
{
size_t len = 0;
const unsigned char *val = NULL;
unsigned short code;
struct thread_data *res = data->state.async.tdata;
struct Curl_https_rrinfo *hi = &res->hinfo;
code = ares_dns_rr_get_opt(rr, key, idx, &val, &len);
switch(code) {
case HTTPS_RR_CODE_ALPN: /* str_list */
Curl_httpsrr_decode_alpn(val, len, hi->alpns);
infof(data, "HTTPS RR ALPN: %u %u %u %u",
hi->alpns[0], hi->alpns[1], hi->alpns[2], hi->alpns[3]);
break;
case HTTPS_RR_CODE_NO_DEF_ALPN:
infof(data, "HTTPS RR no-def-alpn");
break;
case HTTPS_RR_CODE_IPV4: /* addr4 list */
infof(data, "HTTPS RR IPv4");
break;
case HTTPS_RR_CODE_ECH:
infof(data, "HTTPS RR ECH");
break;
case HTTPS_RR_CODE_IPV6: /* addr6 list */
infof(data, "HTTPS RR IPv6");
break;
case HTTPS_RR_CODE_PORT:
infof(data, "HTTPS RR port");
break;
default:
infof(data, "HTTPS RR unknown code");
break;
}
}
void Curl_dnsrec_done_cb(void *arg, ares_status_t status,
size_t timeouts,
const ares_dns_record_t *dnsrec)
{
struct Curl_easy *data = arg;
size_t i;
#ifdef CURLRES_ARES
struct thread_data *res = data->state.async.tdata;
res->num_pending--;
#endif
(void)timeouts;
if((ARES_SUCCESS != status) || !dnsrec)
return;
for(i = 0; i < ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_ANSWER); i++) {
size_t opt;
const ares_dns_rr_t *rr =
ares_dns_record_rr_get_const(dnsrec, ARES_SECTION_ANSWER, i);
if(ares_dns_rr_get_type(rr) != ARES_REC_TYPE_HTTPS)
continue;
/* When SvcPriority is 0, the SVCB record is in AliasMode. Otherwise, it
is in ServiceMode */
infof(data, "HTTPS RR priority: %u",
ares_dns_rr_get_u16(rr, ARES_RR_HTTPS_PRIORITY));
for(opt = 0; opt < ares_dns_rr_get_opt_cnt(rr, ARES_RR_HTTPS_PARAMS);
opt++)
httpsrr_opt(data, rr, ARES_RR_HTTPS_PARAMS, opt);
}
}
#endif /* USE_ARES */
#endif /* USE_HTTPSRR */

View File

@ -24,6 +24,36 @@
*
***************************************************************************/
#include "curl_setup.h"
#ifdef USE_ARES
#include <ares.h>
#endif
#ifdef USE_HTTPSRR
#define CURL_MAXLEN_host_name 253
#define MAX_HTTPSRR_ALPNS 4
struct Curl_https_rrinfo {
/*
* Fields from HTTPS RR. The only mandatory fields are priority and target.
* See https://datatracker.ietf.org/doc/html/rfc9460#section-14.3.2
*/
char *target;
unsigned char *ipv4hints; /* keytag = 4 */
size_t ipv4hints_len;
unsigned char *echconfiglist; /* keytag = 5 */
size_t echconfiglist_len;
unsigned char *ipv6hints; /* keytag = 6 */
size_t ipv6hints_len;
unsigned char alpns[MAX_HTTPSRR_ALPNS]; /* keytag = 1 */
/* store parsed alpnid entries in the array, end with ALPN_none */
int port; /* -1 means not set */
uint16_t priority;
bool no_def_alpn; /* keytag = 2 */
};
#endif
/*
* Code points for DNS wire format SvcParams as per RFC 9460
@ -38,4 +68,9 @@
CURLcode Curl_httpsrr_decode_alpn(const unsigned char *cp, size_t len,
unsigned char *alpns);
#if defined(USE_ARES) && defined(USE_HTTPSRR)
void Curl_dnsrec_done_cb(void *arg, ares_status_t status,
size_t timeouts,
const ares_dns_record_t *dnsrec);
#endif
#endif /* HEADER_CURL_HTTPSRR_H */

View File

@ -467,11 +467,18 @@ static const struct feat features_table[] = {
#ifdef HAVE_BROTLI
FEATURE("brotli", NULL, CURL_VERSION_BROTLI),
#endif
#if defined(CURLRES_ARES) && defined(CURLRES_THREADED)
FEATURE("c-ares-rr", NULL, 0),
#endif
#ifdef DEBUGBUILD
FEATURE("Debug", NULL, CURL_VERSION_DEBUG),
#endif
#if defined(USE_SSL) && defined(USE_ECH)
FEATURE("ECH", ech_present, 0),
#ifndef USE_HTTPSRR
#error "ECH enabled but not HTTPSRR, must be a config error"
#endif
#endif
#ifdef USE_GSASL
FEATURE("gsasl", NULL, CURL_VERSION_GSASL),
@ -492,6 +499,9 @@ static const struct feat features_table[] = {
!defined(CURL_DISABLE_HTTP)
FEATURE("HTTPS-proxy", https_proxy_present, CURL_VERSION_HTTPS_PROXY),
#endif
#if defined(USE_HTTPSRR)
FEATURE("HTTPSRR", NULL, 0),
#endif
#if defined(USE_LIBIDN2) || defined(USE_WIN32_IDN) || defined(USE_APPLE_IDN)
FEATURE("IDN", idn_present, CURL_VERSION_IDN),
#endif

View File

@ -29,7 +29,7 @@ dnl CURL_CHECK_OPTION_THREADED_RESOLVER
dnl -------------------------------------------------
dnl Verify if configure has been invoked with option
dnl --enable-threaded-resolver or --disable-threaded-resolver, and
dnl set shell variable want_thres as appropriate.
dnl set shell variable want_threaded_resolver as appropriate.
AC_DEFUN([CURL_CHECK_OPTION_THREADED_RESOLVER], [
AC_MSG_CHECKING([whether to enable the threaded resolver])
@ -41,25 +41,29 @@ AS_HELP_STRING([--disable-threaded-resolver],[Disable threaded resolver]),
case "$OPT_THRES" in
no)
dnl --disable-threaded-resolver option used
want_thres="no"
want_threaded_resolver="no"
;;
yes)
dnl --enable-threaded-resolver option used
want_thres="yes"
want_threaded_resolver="yes"
;;
*)
dnl configure option not specified
case $host_os in
msdos* | amiga*)
want_thres="no"
want_threaded_resolver="no"
;;
*)
want_thres="yes"
if test "$want_ares" = "yes"; then
want_threaded_resolver="no"
else
want_threaded_resolver="yes"
fi
;;
esac
;;
esac
AC_MSG_RESULT([$want_thres])
AC_MSG_RESULT([$want_threaded_resolver])
])
dnl CURL_CHECK_OPTION_ARES
@ -281,53 +285,6 @@ AS_HELP_STRING([--disable-symbol-hiding],[Disable hiding of library internal sym
])
dnl CURL_CHECK_OPTION_THREADS
dnl -------------------------------------------------
dnl Verify if configure has been invoked with option
dnl --enable-threads or --disable-threads, and
dnl set shell variable want_threads as appropriate.
dnl AC_DEFUN([CURL_CHECK_OPTION_THREADS], [
dnl AC_BEFORE([$0],[CURL_CHECK_LIB_THREADS])dnl
dnl AC_MSG_CHECKING([whether to enable threads for DNS lookups])
dnl OPT_THREADS="default"
dnl AC_ARG_ENABLE(threads,
dnl AS_HELP_STRING([--enable-threads@<:@=PATH@:>@],[Enable threads for DNS lookups])
dnl AS_HELP_STRING([--disable-threads],[Disable threads for DNS lookups]),
dnl OPT_THREADS=$enableval)
dnl case "$OPT_THREADS" in
dnl no)
dnl dnl --disable-threads option used
dnl want_threads="no"
dnl AC_MSG_RESULT([no])
dnl ;;
dnl default)
dnl dnl configure option not specified
dnl want_threads="no"
dnl AC_MSG_RESULT([(assumed) no])
dnl ;;
dnl *)
dnl dnl --enable-threads option used
dnl want_threads="yes"
dnl want_threads_path="$enableval"
dnl AC_MSG_RESULT([yes])
dnl ;;
dnl esac
dnl #
dnl if test "$want_ares" = "assume_yes"; then
dnl if test "$want_threads" = "yes"; then
dnl AC_MSG_CHECKING([whether to ignore c-ares enabling assumed setting])
dnl AC_MSG_RESULT([yes])
dnl want_ares="no"
dnl else
dnl want_ares="yes"
dnl fi
dnl fi
dnl if test "$want_threads" = "yes" && test "$want_ares" = "yes"; then
dnl AC_MSG_ERROR([options --enable-ares and --enable-threads are mutually exclusive, at most one may be enabled.])
dnl fi
dnl ])
dnl CURL_CHECK_OPTION_RT
dnl -------------------------------------------------
dnl Verify if configure has been invoked with option
@ -612,7 +569,7 @@ AS_HELP_STRING([--disable-httpsrr],[Disable HTTPSRR support]),
*)
dnl --enable-httpsrr option used
want_httpsrr="yes"
curl_httpsrr_msg="enabled (--disable-httpsrr)"
curl_httpsrr_msg="enabled"
AC_MSG_RESULT([yes])
;;
esac

View File

@ -434,7 +434,8 @@ Features testable here are:
- `AppleIDN`
- `bearssl`
- `brotli`
- `c-ares`
- `c-ares` - c-ares is used for (all) name resolves
- `c-ares-rr` - c-ares is used for additional records only
- `CharConv`
- `codeset-utf8`. If the running codeset is UTF-8 capable.
- `cookies`

View File

@ -28,7 +28,7 @@ Compare curl --version with curl-config --features
# Verify data after the test has been "shot"
<verify>
<postcheck>
%SRCDIR/libtest/test1013.pl ../curl-config %LOGDIR/stdout%TESTNUMBER features
%SRCDIR/libtest/test1013.pl ../curl-config %LOGDIR/stdout%TESTNUMBER features > %LOGDIR/result%TESTNUMBER
</postcheck>
<errorcode>
0

View File

@ -205,6 +205,6 @@ test_cleanup:
CURLcode test(char *URL)
{
(void)URL;
return 0;
return CURLE_OK;
}
#endif

View File

@ -698,6 +698,8 @@ sub checksystemfeatures {
$feature{"Unicode"} = $feat =~ /Unicode/i;
# Thread-safe init
$feature{"threadsafe"} = $feat =~ /threadsafe/i;
$feature{"HTTPSRR"} = $feat =~ /HTTPSRR/;
$feature{"c-ares-rr"} = $feat =~ /c-ares-rr/;
}
#
# Test harness currently uses a non-stunnel server in order to
@ -822,7 +824,6 @@ sub checksystemfeatures {
$feature{"large-time"} = 1;
$feature{"large-size"} = 1;
$feature{"sha512-256"} = 1;
$feature{"HTTPSRR"} = 1;
$feature{"local-http"} = servers::localhttp();
$feature{"codeset-utf8"} = lc(langinfo(CODESET())) eq "utf-8";

View File

@ -115,9 +115,6 @@ static const char *disabled[]={
#ifndef CURL_CA_SEARCH_SAFE
"win32-ca-search-safe",
#endif
#endif
#ifndef USE_HTTPSRR
"HTTPSRR",
#endif
NULL
};