curl 2025-02-05 (34cf9d54)

Code extracted from:

    https://github.com/curl/curl.git

at commit 34cf9d54a46598c44938aa7598820484d7af7133 (curl-8_12_0).
This commit is contained in:
Curl Upstream
2025-02-05 07:42:54 +01:00
committed by Brad King
parent 4cebf01c70
commit 48b13baebc
208 changed files with 8147 additions and 6676 deletions

View File

@@ -29,11 +29,13 @@ if(WIN32 AND (ENABLE_DEBUG OR ENABLE_CURLDEBUG))
# e.g. curl_easy_perform_ev() or curl_dbg_*(),
# so disable symbol hiding for debug builds and for memory tracking.
set(CURL_HIDDEN_SYMBOLS OFF)
elseif(DOS OR AMIGA)
set(CURL_HIDDEN_SYMBOLS OFF)
endif()
set(CURL_HIDES_PRIVATE_SYMBOLS FALSE)
unset(CURL_EXTERN_SYMBOL)
unset(CURL_CFLAG_SYMBOLS_HIDE)
set(CURL_EXTERN_SYMBOL "")
set(CURL_CFLAG_SYMBOLS_HIDE "")
if(CURL_HIDDEN_SYMBOLS)
if(CMAKE_C_COMPILER_ID MATCHES "Clang" AND NOT MSVC)

View File

@@ -50,7 +50,6 @@ int main(void)
int flags = 0;
if(0 != fcntl(0, F_SETFL, flags | O_NONBLOCK))
return 1;
;
return 0;
}
#endif
@@ -147,24 +146,21 @@ int main(void) { return 0; }
#endif
#ifdef HAVE_FILE_OFFSET_BITS
#ifdef _FILE_OFFSET_BITS
#undef _FILE_OFFSET_BITS
#endif
#define _FILE_OFFSET_BITS 64
#include <sys/types.h>
/* Check that off_t can represent 2**63 - 1 correctly.
We cannot simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
/* Check that off_t can represent 2**63 - 1 correctly.
We cannot simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
int main(void) { return 0; }
#endif
#ifdef HAVE_IOCTLSOCKET
/* includes start */
#ifdef _WIN32
# include <winsock2.h>
#endif
@@ -180,10 +176,7 @@ int main(void)
#endif
#ifdef HAVE_IOCTLSOCKET_CAMEL
/* includes start */
#ifdef _WIN32
# include <winsock2.h>
#endif
#include <proto/bsdsocket.h>
int main(void)
{
/* IoctlSocket source code */
@@ -195,9 +188,9 @@ int main(void)
#endif
#ifdef HAVE_IOCTLSOCKET_CAMEL_FIONBIO
/* includes start */
#ifdef _WIN32
# include <winsock2.h>
#include <proto/bsdsocket.h>
#ifdef HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
#endif
int main(void)
{
@@ -211,7 +204,6 @@ int main(void)
#endif
#ifdef HAVE_IOCTLSOCKET_FIONBIO
/* includes start */
#ifdef _WIN32
# include <winsock2.h>
#endif
@@ -227,7 +219,6 @@ int main(void)
#ifdef HAVE_IOCTL_FIONBIO
/* headers for FIONBIO test */
/* includes start */
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
@@ -255,7 +246,6 @@ int main(void)
#ifdef HAVE_IOCTL_SIOCGIFADDR
/* headers for FIONBIO test */
/* includes start */
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
@@ -283,18 +273,15 @@ int main(void)
#endif
#ifdef HAVE_SETSOCKOPT_SO_NONBLOCK
/* includes start */
#ifdef _WIN32
# include <winsock2.h>
#endif
/* includes start */
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
/* includes end */
int main(void)
{
if(0 != setsockopt(0, SOL_SOCKET, SO_NONBLOCK, 0, 0))
@@ -372,7 +359,6 @@ int main(void)
#endif
#ifdef HAVE_ATOMIC
/* includes start */
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
@@ -382,8 +368,6 @@ int main(void)
#ifdef HAVE_STDATOMIC_H
# include <stdatomic.h>
#endif
/* includes end */
int main(void)
{
_Atomic int i = 1;
@@ -393,14 +377,12 @@ int main(void)
#endif
#ifdef HAVE_WIN32_WINNT
/* includes start */
#ifdef _WIN32
# ifndef NOGDI
# define NOGDI
# define NOGDI
# endif
# include <windows.h>
#endif
/* includes end */
#define enquote(x) #x
#define expand(x) enquote(x)
@@ -411,3 +393,20 @@ int main(void)
return 0;
}
#endif
#ifdef MINGW64_VERSION
#ifdef __MINGW32__
# include <_mingw.h>
#endif
#define enquote(x) #x
#define expand(x) enquote(x)
#pragma message("MINGW64_VERSION=" \
expand(__MINGW64_VERSION_MAJOR) "." \
expand(__MINGW64_VERSION_MINOR))
int main(void)
{
return 0;
}
#endif

View File

@@ -34,47 +34,47 @@
# - `BROTLI_FOUND`: System has brotli.
# - `BROTLI_INCLUDE_DIRS`: The brotli include directories.
# - `BROTLI_LIBRARIES`: The brotli library names.
# - `BROTLI_LIBRARY_DIRS`: The brotli library directories.
# - `BROTLI_PC_REQUIRES`: The brotli pkg-config packages.
# - `BROTLI_CFLAGS`: Required compiler flags.
# - `BROTLI_VERSION`: Version of brotli.
if(CURL_USE_PKGCONFIG)
set(BROTLI_PC_REQUIRES "libbrotlidec")
if(CURL_USE_PKGCONFIG AND
NOT DEFINED BROTLI_INCLUDE_DIR AND
NOT DEFINED BROTLICOMMON_LIBRARY AND
NOT DEFINED BROTLIDEC_LIBRARY)
find_package(PkgConfig QUIET)
pkg_check_modules(PC_BROTLI "libbrotlidec")
pkg_check_modules(BROTLI "libbrotlicommon")
pkg_check_modules(BROTLIDEC ${BROTLI_PC_REQUIRES})
endif()
find_path(BROTLI_INCLUDE_DIR "brotli/decode.h"
HINTS
${PC_BROTLI_INCLUDEDIR}
${PC_BROTLI_INCLUDE_DIRS}
)
if(BROTLI_FOUND AND BROTLIDEC_FOUND)
list(APPEND BROTLIDEC_LIBRARIES ${BROTLI_LIBRARIES}) # order is significant: brotlidec then brotlicommon
list(REVERSE BROTLIDEC_LIBRARIES)
list(REMOVE_DUPLICATES BROTLIDEC_LIBRARIES)
list(REVERSE BROTLIDEC_LIBRARIES)
set(BROTLI_LIBRARIES ${BROTLIDEC_LIBRARIES})
string(REPLACE ";" " " BROTLI_CFLAGS "${BROTLI_CFLAGS}")
message(STATUS "Found Brotli (via pkg-config): ${BROTLI_INCLUDE_DIRS} (found version \"${BROTLI_VERSION}\")")
else()
find_path(BROTLI_INCLUDE_DIR "brotli/decode.h")
find_library(BROTLICOMMON_LIBRARY NAMES "brotlicommon")
find_library(BROTLIDEC_LIBRARY NAMES "brotlidec")
find_library(BROTLICOMMON_LIBRARY NAMES "brotlicommon"
HINTS
${PC_BROTLI_LIBDIR}
${PC_BROTLI_LIBRARY_DIRS}
)
find_library(BROTLIDEC_LIBRARY NAMES "brotlidec"
HINTS
${PC_BROTLI_LIBDIR}
${PC_BROTLI_LIBRARY_DIRS}
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Brotli
REQUIRED_VARS
BROTLI_INCLUDE_DIR
BROTLIDEC_LIBRARY
BROTLICOMMON_LIBRARY
)
if(PC_BROTLI_VERSION)
set(BROTLI_VERSION ${PC_BROTLI_VERSION})
if(BROTLI_FOUND)
set(BROTLI_INCLUDE_DIRS ${BROTLI_INCLUDE_DIR})
set(BROTLI_LIBRARIES ${BROTLIDEC_LIBRARY} ${BROTLICOMMON_LIBRARY})
endif()
mark_as_advanced(BROTLI_INCLUDE_DIR BROTLIDEC_LIBRARY BROTLICOMMON_LIBRARY)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Brotli
REQUIRED_VARS
BROTLI_INCLUDE_DIR
BROTLIDEC_LIBRARY
BROTLICOMMON_LIBRARY
VERSION_VAR
BROTLI_VERSION
)
if(BROTLI_FOUND)
set(BROTLI_INCLUDE_DIRS ${BROTLI_INCLUDE_DIR})
set(BROTLI_LIBRARIES ${BROTLIDEC_LIBRARY} ${BROTLICOMMON_LIBRARY})
endif()
mark_as_advanced(BROTLI_INCLUDE_DIR BROTLIDEC_LIBRARY BROTLICOMMON_LIBRARY)

View File

@@ -33,58 +33,64 @@
# - `CARES_FOUND`: System has c-ares.
# - `CARES_INCLUDE_DIRS`: The c-ares include directories.
# - `CARES_LIBRARIES`: The c-ares library names.
# - `CARES_LIBRARY_DIRS`: The c-ares library directories.
# - `CARES_PC_REQUIRES`: The c-ares pkg-config packages.
# - `CARES_CFLAGS`: Required compiler flags.
# - `CARES_VERSION`: Version of c-ares.
if(CURL_USE_PKGCONFIG)
set(CARES_PC_REQUIRES "libcares")
if(CURL_USE_PKGCONFIG AND
NOT DEFINED CARES_INCLUDE_DIR AND
NOT DEFINED CARES_LIBRARY)
find_package(PkgConfig QUIET)
pkg_check_modules(PC_CARES "libcares")
pkg_check_modules(CARES ${CARES_PC_REQUIRES})
endif()
find_path(CARES_INCLUDE_DIR NAMES "ares.h"
HINTS
${PC_CARES_INCLUDEDIR}
${PC_CARES_INCLUDE_DIRS}
)
find_library(CARES_LIBRARY NAMES ${CARES_NAMES} "cares"
HINTS
${PC_CARES_LIBDIR}
${PC_CARES_LIBRARY_DIRS}
)
if(PC_CARES_VERSION)
set(CARES_VERSION ${PC_CARES_VERSION})
elseif(CARES_INCLUDE_DIR AND EXISTS "${CARES_INCLUDE_DIR}/ares_version.h")
set(_version_regex1 "#[\t ]*define[\t ]+ARES_VERSION_MAJOR[\t ]+([0-9]+).*")
set(_version_regex2 "#[\t ]*define[\t ]+ARES_VERSION_MINOR[\t ]+([0-9]+).*")
set(_version_regex3 "#[\t ]*define[\t ]+ARES_VERSION_PATCH[\t ]+([0-9]+).*")
file(STRINGS "${CARES_INCLUDE_DIR}/ares_version.h" _version_str1 REGEX "${_version_regex1}")
file(STRINGS "${CARES_INCLUDE_DIR}/ares_version.h" _version_str2 REGEX "${_version_regex2}")
file(STRINGS "${CARES_INCLUDE_DIR}/ares_version.h" _version_str3 REGEX "${_version_regex3}")
string(REGEX REPLACE "${_version_regex1}" "\\1" _version_str1 "${_version_str1}")
string(REGEX REPLACE "${_version_regex2}" "\\1" _version_str2 "${_version_str2}")
string(REGEX REPLACE "${_version_regex3}" "\\1" _version_str3 "${_version_str3}")
set(CARES_VERSION "${_version_str1}.${_version_str2}.${_version_str3}")
unset(_version_regex1)
unset(_version_regex2)
unset(_version_regex3)
unset(_version_str1)
unset(_version_str2)
unset(_version_str3)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Cares
REQUIRED_VARS
CARES_INCLUDE_DIR
CARES_LIBRARY
VERSION_VAR
CARES_VERSION
)
if(CARES_FOUND)
set(CARES_INCLUDE_DIRS ${CARES_INCLUDE_DIR})
set(CARES_LIBRARIES ${CARES_LIBRARY})
string(REPLACE ";" " " CARES_CFLAGS "${CARES_CFLAGS}")
message(STATUS "Found Cares (via pkg-config): ${CARES_INCLUDE_DIRS} (found version \"${CARES_VERSION}\")")
else()
find_path(CARES_INCLUDE_DIR NAMES "ares.h")
find_library(CARES_LIBRARY NAMES ${CARES_NAMES} "cares")
unset(CARES_VERSION CACHE)
if(CARES_INCLUDE_DIR AND EXISTS "${CARES_INCLUDE_DIR}/ares_version.h")
set(_version_regex1 "#[\t ]*define[\t ]+ARES_VERSION_MAJOR[\t ]+([0-9]+).*")
set(_version_regex2 "#[\t ]*define[\t ]+ARES_VERSION_MINOR[\t ]+([0-9]+).*")
set(_version_regex3 "#[\t ]*define[\t ]+ARES_VERSION_PATCH[\t ]+([0-9]+).*")
file(STRINGS "${CARES_INCLUDE_DIR}/ares_version.h" _version_str1 REGEX "${_version_regex1}")
file(STRINGS "${CARES_INCLUDE_DIR}/ares_version.h" _version_str2 REGEX "${_version_regex2}")
file(STRINGS "${CARES_INCLUDE_DIR}/ares_version.h" _version_str3 REGEX "${_version_regex3}")
string(REGEX REPLACE "${_version_regex1}" "\\1" _version_str1 "${_version_str1}")
string(REGEX REPLACE "${_version_regex2}" "\\1" _version_str2 "${_version_str2}")
string(REGEX REPLACE "${_version_regex3}" "\\1" _version_str3 "${_version_str3}")
set(CARES_VERSION "${_version_str1}.${_version_str2}.${_version_str3}")
unset(_version_regex1)
unset(_version_regex2)
unset(_version_regex3)
unset(_version_str1)
unset(_version_str2)
unset(_version_str3)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Cares
REQUIRED_VARS
CARES_INCLUDE_DIR
CARES_LIBRARY
VERSION_VAR
CARES_VERSION
)
if(CARES_FOUND)
set(CARES_INCLUDE_DIRS ${CARES_INCLUDE_DIR})
set(CARES_LIBRARIES ${CARES_LIBRARY})
endif()
mark_as_advanced(CARES_INCLUDE_DIR CARES_LIBRARY)
endif()
mark_as_advanced(CARES_INCLUDE_DIR CARES_LIBRARY)
if(CARES_FOUND AND WIN32)
list(APPEND CARES_LIBRARIES "iphlpapi") # for if_indextoname and others
endif()

View File

@@ -99,7 +99,7 @@ if(NOT _GSS_FOUND) # Not found by pkg-config. Let us take more traditional appr
string(REGEX REPLACE " +-([^I][^ \\t;]*)" ";-\\1" _GSS_CFLAGS "${_GSS_CFLAGS}")
foreach(_flag IN LISTS _GSS_CFLAGS)
if(_flag MATCHES "^-I.*")
if(_flag MATCHES "^-I")
string(REGEX REPLACE "^-I" "" _val "${_flag}")
list(APPEND _GSS_INCLUDE_DIRS "${_val}")
else()
@@ -123,10 +123,10 @@ if(NOT _GSS_FOUND) # Not found by pkg-config. Let us take more traditional appr
string(REGEX REPLACE " +-([^Ll][^ \\t;]*)" ";-\\1" _gss_lib_flags "${_gss_lib_flags}")
foreach(_flag IN LISTS _gss_lib_flags)
if(_flag MATCHES "^-l.*")
if(_flag MATCHES "^-l")
string(REGEX REPLACE "^-l" "" _val "${_flag}")
list(APPEND _GSS_LIBRARIES "${_val}")
elseif(_flag MATCHES "^-L.*")
elseif(_flag MATCHES "^-L")
string(REGEX REPLACE "^-L" "" _val "${_flag}")
list(APPEND _GSS_LIBRARY_DIRS "${_val}")
endif()
@@ -156,7 +156,7 @@ if(NOT _GSS_FOUND) # Not found by pkg-config. Let us take more traditional appr
if(_gss_configure_failed)
set(GSS_FLAVOUR "Heimdal") # most probably, should not really matter
else()
if(_gss_vendor MATCHES ".*H|heimdal.*")
if(_gss_vendor MATCHES "H|heimdal")
set(GSS_FLAVOUR "Heimdal")
else()
set(GSS_FLAVOUR "MIT")
@@ -175,7 +175,7 @@ if(NOT _GSS_FOUND) # Not found by pkg-config. Let us take more traditional appr
if(_GSS_INCLUDE_DIRS) # jay, we have found something
cmake_push_check_state()
set(CMAKE_REQUIRED_INCLUDES "${_GSS_INCLUDE_DIRS}")
list(APPEND CMAKE_REQUIRED_INCLUDES "${_GSS_INCLUDE_DIRS}")
check_include_files("gssapi/gssapi_generic.h;gssapi/gssapi_krb5.h" _gss_have_mit_headers)
if(_gss_have_mit_headers)

111
CMake/FindLDAP.cmake Normal file
View File

@@ -0,0 +1,111 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) 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
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
# Find the ldap library
#
# Input variables:
#
# - `LDAP_INCLUDE_DIR`: The ldap include directory.
# - `LDAP_LIBRARY`: Path to `ldap` library.
# - `LDAP_LBER_LIBRARY`: Path to `lber` library.
#
# Result variables:
#
# - `LDAP_FOUND`: System has ldap.
# - `LDAP_INCLUDE_DIRS`: The ldap include directories.
# - `LDAP_LIBRARIES`: The ldap library names.
# - `LDAP_LIBRARY_DIRS`: The ldap library directories.
# - `LDAP_PC_REQUIRES`: The ldap pkg-config packages.
# - `LDAP_CFLAGS`: Required compiler flags.
# - `LDAP_VERSION`: Version of ldap.
set(LDAP_PC_REQUIRES "ldap")
if(CURL_USE_PKGCONFIG AND
NOT DEFINED LDAP_INCLUDE_DIR AND
NOT DEFINED LDAP_LIBRARY AND
NOT DEFINED LDAP_LBER_LIBRARY)
find_package(PkgConfig QUIET)
pkg_check_modules(LDAP ${LDAP_PC_REQUIRES})
pkg_check_modules(LDAP_LBER "lber")
endif()
if(LDAP_FOUND AND LDAP_LBER_FOUND)
list(APPEND LDAP_LIBRARIES ${LDAP_LBER_LIBRARIES})
list(REVERSE LDAP_LIBRARIES)
list(REMOVE_DUPLICATES LDAP_LIBRARIES)
list(REVERSE LDAP_LIBRARIES)
string(REPLACE ";" " " LDAP_CFLAGS "${LDAP_CFLAGS}")
message(STATUS "Found LDAP (via pkg-config): ${LDAP_INCLUDE_DIRS} (found version \"${LDAP_VERSION}\")")
else()
set(LDAP_PC_REQUIRES "") # Depend on pkg-config only when found via pkg-config
# On Apple the SDK LDAP gets picked up from
# 'MacOSX.sdk/System/Library/Frameworks/LDAP.framework/Headers', which contains
# ldap.h and lber.h both being stubs to include <ldap.h> and <lber.h>.
# This causes an infinite inclusion loop in compile. Also do this for libraries
# to avoid picking up the 'ldap.framework' with a full path.
set(_save_cmake_system_framework_path ${CMAKE_SYSTEM_FRAMEWORK_PATH})
set(CMAKE_SYSTEM_FRAMEWORK_PATH "")
find_path(LDAP_INCLUDE_DIR NAMES "ldap.h")
find_library(LDAP_LIBRARY NAMES "ldap")
find_library(LDAP_LBER_LIBRARY NAMES "lber")
set(CMAKE_SYSTEM_FRAMEWORK_PATH ${_save_cmake_system_framework_path})
unset(LDAP_VERSION CACHE)
if(LDAP_INCLUDE_DIR AND EXISTS "${LDAP_INCLUDE_DIR}/ldap_features.h")
set(_version_regex1 "#[\t ]*define[\t ]+LDAP_VENDOR_VERSION_MAJOR[\t ]+([0-9]+).*")
set(_version_regex2 "#[\t ]*define[\t ]+LDAP_VENDOR_VERSION_MINOR[\t ]+([0-9]+).*")
set(_version_regex3 "#[\t ]*define[\t ]+LDAP_VENDOR_VERSION_PATCH[\t ]+([0-9]+).*")
file(STRINGS "${LDAP_INCLUDE_DIR}/ldap_features.h" _version_str1 REGEX "${_version_regex1}")
file(STRINGS "${LDAP_INCLUDE_DIR}/ldap_features.h" _version_str2 REGEX "${_version_regex2}")
file(STRINGS "${LDAP_INCLUDE_DIR}/ldap_features.h" _version_str3 REGEX "${_version_regex3}")
string(REGEX REPLACE "${_version_regex1}" "\\1" _version_str1 "${_version_str1}")
string(REGEX REPLACE "${_version_regex2}" "\\1" _version_str2 "${_version_str2}")
string(REGEX REPLACE "${_version_regex3}" "\\1" _version_str3 "${_version_str3}")
set(LDAP_VERSION "${_version_str1}.${_version_str2}.${_version_str3}")
unset(_version_regex1)
unset(_version_regex2)
unset(_version_regex3)
unset(_version_str1)
unset(_version_str2)
unset(_version_str3)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(LDAP
REQUIRED_VARS
LDAP_INCLUDE_DIR
LDAP_LIBRARY
LDAP_LBER_LIBRARY
VERSION_VAR
LDAP_VERSION
)
if(LDAP_FOUND)
set(LDAP_INCLUDE_DIRS ${LDAP_INCLUDE_DIR})
set(LDAP_LIBRARIES ${LDAP_LIBRARY} ${LDAP_LBER_LIBRARY})
endif()
mark_as_advanced(LDAP_INCLUDE_DIR LDAP_LIBRARY LDAP_LBER_LIBRARY)
endif()

View File

@@ -34,14 +34,17 @@
# - `LIBGSASL_INCLUDE_DIRS`: The libgsasl include directories.
# - `LIBGSASL_LIBRARIES`: The libgsasl library names.
# - `LIBGSASL_LIBRARY_DIRS`: The libgsasl library directories.
# - `LIBGSASL_PC_REQUIRES`: The libgsasl pkg-config packages.
# - `LIBGSASL_CFLAGS`: Required compiler flags.
# - `LIBGSASL_VERSION`: Version of libgsasl.
set(LIBGSASL_PC_REQUIRES "libgsasl")
if(CURL_USE_PKGCONFIG AND
NOT DEFINED LIBGSASL_INCLUDE_DIR AND
NOT DEFINED LIBGSASL_LIBRARY)
find_package(PkgConfig QUIET)
pkg_check_modules(LIBGSASL "libgsasl")
pkg_check_modules(LIBGSASL ${LIBGSASL_PC_REQUIRES})
endif()
if(LIBGSASL_FOUND)

View File

@@ -34,14 +34,17 @@
# - `LIBIDN2_INCLUDE_DIRS`: The libidn2 include directories.
# - `LIBIDN2_LIBRARIES`: The libidn2 library names.
# - `LIBIDN2_LIBRARY_DIRS`: The libidn2 library directories.
# - `LIBIDN2_PC_REQUIRES`: The libidn2 pkg-config packages.
# - `LIBIDN2_CFLAGS`: Required compiler flags.
# - `LIBIDN2_VERSION`: Version of libidn2.
set(LIBIDN2_PC_REQUIRES "libidn2")
if(CURL_USE_PKGCONFIG AND
NOT DEFINED LIBIDN2_INCLUDE_DIR AND
NOT DEFINED LIBIDN2_LIBRARY)
find_package(PkgConfig QUIET)
pkg_check_modules(LIBIDN2 "libidn2")
pkg_check_modules(LIBIDN2 ${LIBIDN2_PC_REQUIRES})
endif()
if(LIBIDN2_FOUND)

View File

@@ -33,48 +33,50 @@
# - `LIBPSL_FOUND`: System has libpsl.
# - `LIBPSL_INCLUDE_DIRS`: The libpsl include directories.
# - `LIBPSL_LIBRARIES`: The libpsl library names.
# - `LIBPSL_LIBRARY_DIRS`: The libpsl library directories.
# - `LIBPSL_PC_REQUIRES`: The libpsl pkg-config packages.
# - `LIBPSL_CFLAGS`: Required compiler flags.
# - `LIBPSL_VERSION`: Version of libpsl.
if(CURL_USE_PKGCONFIG)
set(LIBPSL_PC_REQUIRES "libpsl")
if(CURL_USE_PKGCONFIG AND
NOT DEFINED LIBPSL_INCLUDE_DIR AND
NOT DEFINED LIBPSL_LIBRARY)
find_package(PkgConfig QUIET)
pkg_check_modules(PC_LIBPSL "libpsl")
pkg_check_modules(LIBPSL ${LIBPSL_PC_REQUIRES})
endif()
find_path(LIBPSL_INCLUDE_DIR NAMES "libpsl.h"
HINTS
${PC_LIBPSL_INCLUDEDIR}
${PC_LIBPSL_INCLUDE_DIRS}
)
if(LIBPSL_FOUND AND LIBPSL_INCLUDE_DIRS)
string(REPLACE ";" " " LIBPSL_CFLAGS "${LIBPSL_CFLAGS}")
message(STATUS "Found Libpsl (via pkg-config): ${LIBPSL_INCLUDE_DIRS} (found version \"${LIBPSL_VERSION}\")")
else()
find_path(LIBPSL_INCLUDE_DIR NAMES "libpsl.h")
find_library(LIBPSL_LIBRARY NAMES "psl" "libpsl")
find_library(LIBPSL_LIBRARY NAMES "psl" "libpsl"
HINTS
${PC_LIBPSL_LIBDIR}
${PC_LIBPSL_LIBRARY_DIRS}
)
unset(LIBPSL_VERSION CACHE)
if(LIBPSL_INCLUDE_DIR AND EXISTS "${LIBPSL_INCLUDE_DIR}/libpsl.h")
set(_version_regex "#[\t ]*define[\t ]+PSL_VERSION[\t ]+\"([^\"]*)\"")
file(STRINGS "${LIBPSL_INCLUDE_DIR}/libpsl.h" _version_str REGEX "${_version_regex}")
string(REGEX REPLACE "${_version_regex}" "\\1" _version_str "${_version_str}")
set(LIBPSL_VERSION "${_version_str}")
unset(_version_regex)
unset(_version_str)
endif()
if(PC_LIBPSL_VERSION)
set(LIBPSL_VERSION ${PC_LIBPSL_VERSION})
elseif(LIBPSL_INCLUDE_DIR AND EXISTS "${LIBPSL_INCLUDE_DIR}/libpsl.h")
set(_version_regex "#[\t ]*define[\t ]+PSL_VERSION[\t ]+\"([^\"]*)\"")
file(STRINGS "${LIBPSL_INCLUDE_DIR}/libpsl.h" _version_str REGEX "${_version_regex}")
string(REGEX REPLACE "${_version_regex}" "\\1" _version_str "${_version_str}")
set(LIBPSL_VERSION "${_version_str}")
unset(_version_regex)
unset(_version_str)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Libpsl
REQUIRED_VARS
LIBPSL_INCLUDE_DIR
LIBPSL_LIBRARY
VERSION_VAR
LIBPSL_VERSION
)
if(LIBPSL_FOUND)
set(LIBPSL_INCLUDE_DIRS ${LIBPSL_INCLUDE_DIR})
set(LIBPSL_LIBRARIES ${LIBPSL_LIBRARY})
endif()
mark_as_advanced(LIBPSL_INCLUDE_DIR LIBPSL_LIBRARY)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Libpsl
REQUIRED_VARS
LIBPSL_INCLUDE_DIR
LIBPSL_LIBRARY
VERSION_VAR
LIBPSL_VERSION
)
if(LIBPSL_FOUND)
set(LIBPSL_INCLUDE_DIRS ${LIBPSL_INCLUDE_DIR})
set(LIBPSL_LIBRARIES ${LIBPSL_LIBRARY})
endif()
mark_as_advanced(LIBPSL_INCLUDE_DIR LIBPSL_LIBRARY)

102
CMake/FindLibrtmp.cmake Normal file
View File

@@ -0,0 +1,102 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) 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
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
# Find the librtmp library
#
# Input variables:
#
# - `LIBRTMP_INCLUDE_DIR`: The librtmp include directory.
# - `LIBRTMP_LIBRARY`: Path to `librtmp` library.
#
# Result variables:
#
# - `LIBRTMP_FOUND`: System has librtmp.
# - `LIBRTMP_INCLUDE_DIRS`: The librtmp include directories.
# - `LIBRTMP_LIBRARIES`: The librtmp library names.
# - `LIBRTMP_LIBRARY_DIRS`: The librtmp library directories.
# - `LIBRTMP_PC_REQUIRES`: The librtmp pkg-config packages.
# - `LIBRTMP_CFLAGS`: Required compiler flags.
# - `LIBRTMP_VERSION`: Version of librtmp.
set(LIBRTMP_PC_REQUIRES "librtmp")
if(CURL_USE_PKGCONFIG AND
NOT DEFINED LIBRTMP_INCLUDE_DIR AND
NOT DEFINED LIBRTMP_LIBRARY)
find_package(PkgConfig QUIET)
pkg_check_modules(LIBRTMP ${LIBRTMP_PC_REQUIRES})
endif()
if(LIBRTMP_FOUND AND LIBRTMP_INCLUDE_DIRS)
string(REPLACE ";" " " LIBRTMP_CFLAGS "${LIBRTMP_CFLAGS}")
message(STATUS "Found Librtmp (via pkg-config): ${LIBRTMP_INCLUDE_DIRS} (found version \"${LIBRTMP_VERSION}\")")
else()
find_path(LIBRTMP_INCLUDE_DIR NAMES "librtmp/rtmp.h")
find_library(LIBRTMP_LIBRARY NAMES "rtmp")
unset(LIBRTMP_VERSION CACHE)
if(LIBRTMP_INCLUDE_DIR AND EXISTS "${LIBRTMP_INCLUDE_DIR}/librtmp/rtmp.h")
set(_version_regex "#[\t ]*define[\t ]+RTMP_LIB_VERSION[\t ]+0x([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F]).*")
file(STRINGS "${LIBRTMP_INCLUDE_DIR}/librtmp/rtmp.h" _version_str REGEX "${_version_regex}")
string(REGEX REPLACE "${_version_regex}" "\\1" _version_str1 "${_version_str}")
string(REGEX REPLACE "${_version_regex}" "\\2" _version_str2 "${_version_str}")
if(CMAKE_VERSION VERSION_LESS 3.13)
# No support for hex version numbers, just strip leading zeroes
string(REGEX REPLACE "^0" "" _version_str1 "${_version_str1}")
string(REGEX REPLACE "^0" "" _version_str2 "${_version_str2}")
else()
math(EXPR _version_str1 "0x${_version_str1}" OUTPUT_FORMAT DECIMAL)
math(EXPR _version_str2 "0x${_version_str2}" OUTPUT_FORMAT DECIMAL)
endif()
set(LIBRTMP_VERSION "${_version_str1}.${_version_str2}")
unset(_version_regex)
unset(_version_str1)
unset(_version_str2)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Librtmp
REQUIRED_VARS
LIBRTMP_INCLUDE_DIR
LIBRTMP_LIBRARY
VERSION_VAR
LIBRTMP_VERSION
)
if(LIBRTMP_FOUND)
set(LIBRTMP_INCLUDE_DIRS ${LIBRTMP_INCLUDE_DIR})
set(LIBRTMP_LIBRARIES ${LIBRTMP_LIBRARY})
endif()
mark_as_advanced(LIBRTMP_INCLUDE_DIR LIBRTMP_LIBRARY)
# Necessary when linking a static librtmp
find_package(OpenSSL)
if(OPENSSL_FOUND)
list(APPEND LIBRTMP_LIBRARIES OpenSSL::SSL OpenSSL::Crypto)
endif()
endif()
if(LIBRTMP_FOUND AND WIN32)
list(APPEND LIBRTMP_LIBRARIES "winmm")
endif()

View File

@@ -25,23 +25,26 @@
#
# Input variables:
#
# LIBSSH_INCLUDE_DIR The libssh include directory.
# LIBSSH_LIBRARY Path to libssh library.
# - `LIBSSH_INCLUDE_DIR`: The libssh include directory.
# - `LIBSSH_LIBRARY`: Path to libssh library.
#
# Result variables:
#
# LIBSSH_FOUND System has libssh.
# LIBSSH_INCLUDE_DIRS The libssh include directories.
# LIBSSH_LIBRARIES The libssh library names.
# LIBSSH_LIBRARY_DIRS The libssh library directories.
# LIBSSH_CFLAGS Required compiler flags.
# LIBSSH_VERSION Version of libssh.
# - `LIBSSH_FOUND`: System has libssh.
# - `LIBSSH_INCLUDE_DIRS`: The libssh include directories.
# - `LIBSSH_LIBRARIES`: The libssh library names.
# - `LIBSSH_LIBRARY_DIRS`: The libssh library directories.
# - `LIBSSH_PC_REQUIRES`: The libssh pkg-config packages.
# - `LIBSSH_CFLAGS`: Required compiler flags.
# - `LIBSSH_VERSION`: Version of libssh.
set(LIBSSH_PC_REQUIRES "libssh")
if(CURL_USE_PKGCONFIG AND
NOT DEFINED LIBSSH_INCLUDE_DIR AND
NOT DEFINED LIBSSH_LIBRARY)
find_package(PkgConfig QUIET)
pkg_check_modules(LIBSSH "libssh")
pkg_check_modules(LIBSSH ${LIBSSH_PC_REQUIRES})
endif()
if(LIBSSH_FOUND)

View File

@@ -33,48 +33,50 @@
# - `LIBSSH2_FOUND`: System has libssh2.
# - `LIBSSH2_INCLUDE_DIRS`: The libssh2 include directories.
# - `LIBSSH2_LIBRARIES`: The libssh2 library names.
# - `LIBSSH2_LIBRARY_DIRS`: The libssh2 library directories.
# - `LIBSSH2_PC_REQUIRES`: The libssh2 pkg-config packages.
# - `LIBSSH2_CFLAGS`: Required compiler flags.
# - `LIBSSH2_VERSION`: Version of libssh2.
if(CURL_USE_PKGCONFIG)
set(LIBSSH2_PC_REQUIRES "libssh2")
if(CURL_USE_PKGCONFIG AND
NOT DEFINED LIBSSH2_INCLUDE_DIR AND
NOT DEFINED LIBSSH2_LIBRARY)
find_package(PkgConfig QUIET)
pkg_check_modules(PC_LIBSSH2 "libssh2")
pkg_check_modules(LIBSSH2 ${LIBSSH2_PC_REQUIRES})
endif()
find_path(LIBSSH2_INCLUDE_DIR NAMES "libssh2.h"
HINTS
${PC_LIBSSH2_INCLUDEDIR}
${PC_LIBSSH2_INCLUDE_DIRS}
)
if(LIBSSH2_FOUND AND LIBSSH2_INCLUDE_DIRS)
string(REPLACE ";" " " LIBSSH2_CFLAGS "${LIBSSH2_CFLAGS}")
message(STATUS "Found Libssh2 (via pkg-config): ${LIBSSH2_INCLUDE_DIRS} (found version \"${LIBSSH2_VERSION}\")")
else()
find_path(LIBSSH2_INCLUDE_DIR NAMES "libssh2.h")
find_library(LIBSSH2_LIBRARY NAMES "ssh2" "libssh2")
find_library(LIBSSH2_LIBRARY NAMES "ssh2" "libssh2"
HINTS
${PC_LIBSSH2_LIBDIR}
${PC_LIBSSH2_LIBRARY_DIRS}
)
unset(LIBSSH2_VERSION CACHE)
if(LIBSSH2_INCLUDE_DIR AND EXISTS "${LIBSSH2_INCLUDE_DIR}/libssh2.h")
set(_version_regex "#[\t ]*define[\t ]+LIBSSH2_VERSION[\t ]+\"([^\"]*)\"")
file(STRINGS "${LIBSSH2_INCLUDE_DIR}/libssh2.h" _version_str REGEX "${_version_regex}")
string(REGEX REPLACE "${_version_regex}" "\\1" _version_str "${_version_str}")
set(LIBSSH2_VERSION "${_version_str}")
unset(_version_regex)
unset(_version_str)
endif()
if(PC_LIBSSH2_VERSION)
set(LIBSSH2_VERSION ${PC_LIBSSH2_VERSION})
elseif(LIBSSH2_INCLUDE_DIR AND EXISTS "${LIBSSH2_INCLUDE_DIR}/libssh2.h")
set(_version_regex "#[\t ]*define[\t ]+LIBSSH2_VERSION[\t ]+\"([^\"]*)\"")
file(STRINGS "${LIBSSH2_INCLUDE_DIR}/libssh2.h" _version_str REGEX "${_version_regex}")
string(REGEX REPLACE "${_version_regex}" "\\1" _version_str "${_version_str}")
set(LIBSSH2_VERSION "${_version_str}")
unset(_version_regex)
unset(_version_str)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Libssh2
REQUIRED_VARS
LIBSSH2_INCLUDE_DIR
LIBSSH2_LIBRARY
VERSION_VAR
LIBSSH2_VERSION
)
if(LIBSSH2_FOUND)
set(LIBSSH2_INCLUDE_DIRS ${LIBSSH2_INCLUDE_DIR})
set(LIBSSH2_LIBRARIES ${LIBSSH2_LIBRARY})
endif()
mark_as_advanced(LIBSSH2_INCLUDE_DIR LIBSSH2_LIBRARY)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Libssh2
REQUIRED_VARS
LIBSSH2_INCLUDE_DIR
LIBSSH2_LIBRARY
VERSION_VAR
LIBSSH2_VERSION
)
if(LIBSSH2_FOUND)
set(LIBSSH2_INCLUDE_DIRS ${LIBSSH2_INCLUDE_DIR})
set(LIBSSH2_LIBRARIES ${LIBSSH2_LIBRARY})
endif()
mark_as_advanced(LIBSSH2_INCLUDE_DIR LIBSSH2_LIBRARY)

View File

@@ -34,14 +34,17 @@
# - `LIBUV_INCLUDE_DIRS`: The libuv include directories.
# - `LIBUV_LIBRARIES`: The libuv library names.
# - `LIBUV_LIBRARY_DIRS`: The libuv library directories.
# - `LIBUV_PC_REQUIRES`: The libuv pkg-config packages.
# - `LIBUV_CFLAGS`: Required compiler flags.
# - `LIBUV_VERSION`: Version of libuv.
set(LIBUV_PC_REQUIRES "libuv")
if(CURL_USE_PKGCONFIG AND
NOT DEFINED LIBUV_INCLUDE_DIR AND
NOT DEFINED LIBUV_LIBRARY)
find_package(PkgConfig QUIET)
pkg_check_modules(LIBUV "libuv")
pkg_check_modules(LIBUV ${LIBUV_PC_REQUIRES})
endif()
if(LIBUV_FOUND)

View File

@@ -38,18 +38,21 @@
# - `MSH3_CFLAGS`: Required compiler flags.
# - `MSH3_VERSION`: Version of msh3.
set(MSH3_PC_REQUIRES "libmsh3")
if(CURL_USE_PKGCONFIG AND
NOT DEFINED MSH3_INCLUDE_DIR AND
NOT DEFINED MSH3_LIBRARY)
find_package(PkgConfig QUIET)
pkg_check_modules(MSH3 "libmsh3")
pkg_check_modules(MSH3 ${MSH3_PC_REQUIRES})
endif()
if(MSH3_FOUND)
set(MSH3_PC_REQUIRES "libmsh3")
string(REPLACE ";" " " MSH3_CFLAGS "${MSH3_CFLAGS}")
message(STATUS "Found MSH3 (via pkg-config): ${MSH3_INCLUDE_DIRS} (found version \"${MSH3_VERSION}\")")
else()
set(MSH3_PC_REQUIRES "") # Depend on pkg-config only when found via pkg-config
find_path(MSH3_INCLUDE_DIR NAMES "msh3.h")
find_library(MSH3_LIBRARY NAMES "msh3")

View File

@@ -46,24 +46,29 @@ if(DEFINED MBEDTLS_INCLUDE_DIRS AND NOT DEFINED MBEDTLS_INCLUDE_DIR)
unset(MBEDTLS_INCLUDE_DIRS)
endif()
set(MBEDTLS_PC_REQUIRES "mbedtls")
if(CURL_USE_PKGCONFIG AND
NOT DEFINED MBEDTLS_INCLUDE_DIR AND
NOT DEFINED MBEDTLS_LIBRARY AND
NOT DEFINED MBEDX509_LIBRARY AND
NOT DEFINED MBEDCRYPTO_LIBRARY)
find_package(PkgConfig QUIET)
pkg_check_modules(MBEDTLS "mbedtls")
pkg_check_modules(MBEDTLS ${MBEDTLS_PC_REQUIRES})
pkg_check_modules(MBEDX509 "mbedx509")
pkg_check_modules(MBEDCRYPTO "mbedcrypto")
endif()
if(MBEDTLS_FOUND AND MBEDX509_FOUND AND MBEDCRYPTO_FOUND)
list(APPEND MBEDTLS_LIBRARIES ${MBEDX509_LIBRARIES} ${MBEDCRYPTO_LIBRARIES})
list(REVERSE MBEDTLS_LIBRARIES)
list(REMOVE_DUPLICATES MBEDTLS_LIBRARIES)
set(MBEDTLS_PC_REQUIRES "mbedtls")
list(REVERSE MBEDTLS_LIBRARIES)
string(REPLACE ";" " " MBEDTLS_CFLAGS "${MBEDTLS_CFLAGS}")
message(STATUS "Found MbedTLS (via pkg-config): ${MBEDTLS_INCLUDE_DIRS} (found version \"${MBEDTLS_VERSION}\")")
else()
set(MBEDTLS_PC_REQUIRES "") # Depend on pkg-config only when found via pkg-config
find_path(MBEDTLS_INCLUDE_DIR NAMES "mbedtls/ssl.h")
find_library(MBEDTLS_LIBRARY NAMES "mbedtls" "libmbedtls")
find_library(MBEDX509_LIBRARY NAMES "mbedx509" "libmbedx509")

View File

@@ -33,48 +33,50 @@
# - `NGHTTP2_FOUND`: System has nghttp2.
# - `NGHTTP2_INCLUDE_DIRS`: The nghttp2 include directories.
# - `NGHTTP2_LIBRARIES`: The nghttp2 library names.
# - `NGHTTP2_LIBRARY_DIRS`: The nghttp2 library directories.
# - `NGHTTP2_PC_REQUIRES`: The nghttp2 pkg-config packages.
# - `NGHTTP2_CFLAGS`: Required compiler flags.
# - `NGHTTP2_VERSION`: Version of nghttp2.
if(CURL_USE_PKGCONFIG)
set(NGHTTP2_PC_REQUIRES "libnghttp2")
if(CURL_USE_PKGCONFIG AND
NOT DEFINED NGHTTP2_INCLUDE_DIR AND
NOT DEFINED NGHTTP2_LIBRARY)
find_package(PkgConfig QUIET)
pkg_check_modules(PC_NGHTTP2 "libnghttp2")
pkg_check_modules(NGHTTP2 ${NGHTTP2_PC_REQUIRES})
endif()
find_path(NGHTTP2_INCLUDE_DIR NAMES "nghttp2/nghttp2.h"
HINTS
${PC_NGHTTP2_INCLUDEDIR}
${PC_NGHTTP2_INCLUDE_DIRS}
)
find_library(NGHTTP2_LIBRARY NAMES "nghttp2" "nghttp2_static"
HINTS
${PC_NGHTTP2_LIBDIR}
${PC_NGHTTP2_LIBRARY_DIRS}
)
if(PC_NGHTTP2_VERSION)
set(NGHTTP2_VERSION ${PC_NGHTTP2_VERSION})
elseif(NGHTTP2_INCLUDE_DIR AND EXISTS "${NGHTTP2_INCLUDE_DIR}/nghttp2/nghttp2ver.h")
set(_version_regex "#[\t ]*define[\t ]+NGHTTP2_VERSION[\t ]+\"([^\"]*)\"")
file(STRINGS "${NGHTTP2_INCLUDE_DIR}/nghttp2/nghttp2ver.h" _version_str REGEX "${_version_regex}")
string(REGEX REPLACE "${_version_regex}" "\\1" _version_str "${_version_str}")
set(NGHTTP2_VERSION "${_version_str}")
unset(_version_regex)
unset(_version_str)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(NGHTTP2
REQUIRED_VARS
NGHTTP2_INCLUDE_DIR
NGHTTP2_LIBRARY
VERSION_VAR
NGHTTP2_VERSION
)
if(NGHTTP2_FOUND)
set(NGHTTP2_INCLUDE_DIRS ${NGHTTP2_INCLUDE_DIR})
set(NGHTTP2_LIBRARIES ${NGHTTP2_LIBRARY})
endif()
string(REPLACE ";" " " NGHTTP2_CFLAGS "${NGHTTP2_CFLAGS}")
message(STATUS "Found NGHTTP2 (via pkg-config): ${NGHTTP2_INCLUDE_DIRS} (found version \"${NGHTTP2_VERSION}\")")
else()
find_path(NGHTTP2_INCLUDE_DIR NAMES "nghttp2/nghttp2.h")
find_library(NGHTTP2_LIBRARY NAMES "nghttp2" "nghttp2_static")
mark_as_advanced(NGHTTP2_INCLUDE_DIR NGHTTP2_LIBRARY)
unset(NGHTTP2_VERSION CACHE)
if(NGHTTP2_INCLUDE_DIR AND EXISTS "${NGHTTP2_INCLUDE_DIR}/nghttp2/nghttp2ver.h")
set(_version_regex "#[\t ]*define[\t ]+NGHTTP2_VERSION[\t ]+\"([^\"]*)\"")
file(STRINGS "${NGHTTP2_INCLUDE_DIR}/nghttp2/nghttp2ver.h" _version_str REGEX "${_version_regex}")
string(REGEX REPLACE "${_version_regex}" "\\1" _version_str "${_version_str}")
set(NGHTTP2_VERSION "${_version_str}")
unset(_version_regex)
unset(_version_str)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(NGHTTP2
REQUIRED_VARS
NGHTTP2_INCLUDE_DIR
NGHTTP2_LIBRARY
VERSION_VAR
NGHTTP2_VERSION
)
if(NGHTTP2_FOUND)
set(NGHTTP2_INCLUDE_DIRS ${NGHTTP2_INCLUDE_DIR})
set(NGHTTP2_LIBRARIES ${NGHTTP2_LIBRARY})
endif()
mark_as_advanced(NGHTTP2_INCLUDE_DIR NGHTTP2_LIBRARY)
endif()

View File

@@ -33,48 +33,50 @@
# - `NGHTTP3_FOUND`: System has nghttp3.
# - `NGHTTP3_INCLUDE_DIRS`: The nghttp3 include directories.
# - `NGHTTP3_LIBRARIES`: The nghttp3 library names.
# - `NGHTTP3_LIBRARY_DIRS`: The nghttp3 library directories.
# - `NGHTTP3_PC_REQUIRES`: The nghttp3 pkg-config packages.
# - `NGHTTP3_CFLAGS`: Required compiler flags.
# - `NGHTTP3_VERSION`: Version of nghttp3.
if(CURL_USE_PKGCONFIG)
set(NGHTTP3_PC_REQUIRES "libnghttp3")
if(CURL_USE_PKGCONFIG AND
NOT DEFINED NGHTTP3_INCLUDE_DIR AND
NOT DEFINED NGHTTP3_LIBRARY)
find_package(PkgConfig QUIET)
pkg_check_modules(PC_NGHTTP3 "libnghttp3")
pkg_check_modules(NGHTTP3 ${NGHTTP3_PC_REQUIRES})
endif()
find_path(NGHTTP3_INCLUDE_DIR NAMES "nghttp3/nghttp3.h"
HINTS
${PC_NGHTTP3_INCLUDEDIR}
${PC_NGHTTP3_INCLUDE_DIRS}
)
find_library(NGHTTP3_LIBRARY NAMES "nghttp3"
HINTS
${PC_NGHTTP3_LIBDIR}
${PC_NGHTTP3_LIBRARY_DIRS}
)
if(PC_NGHTTP3_VERSION)
set(NGHTTP3_VERSION ${PC_NGHTTP3_VERSION})
elseif(NGHTTP3_INCLUDE_DIR AND EXISTS "${NGHTTP3_INCLUDE_DIR}/nghttp3/version.h")
set(_version_regex "#[\t ]*define[\t ]+NGHTTP3_VERSION[\t ]+\"([^\"]*)\"")
file(STRINGS "${NGHTTP3_INCLUDE_DIR}/nghttp3/version.h" _version_str REGEX "${_version_regex}")
string(REGEX REPLACE "${_version_regex}" "\\1" _version_str "${_version_str}")
set(NGHTTP3_VERSION "${_version_str}")
unset(_version_regex)
unset(_version_str)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(NGHTTP3
REQUIRED_VARS
NGHTTP3_INCLUDE_DIR
NGHTTP3_LIBRARY
VERSION_VAR
NGHTTP3_VERSION
)
if(NGHTTP3_FOUND)
set(NGHTTP3_INCLUDE_DIRS ${NGHTTP3_INCLUDE_DIR})
set(NGHTTP3_LIBRARIES ${NGHTTP3_LIBRARY})
endif()
string(REPLACE ";" " " NGHTTP3_CFLAGS "${NGHTTP3_CFLAGS}")
message(STATUS "Found NGHTTP3 (via pkg-config): ${NGHTTP3_INCLUDE_DIRS} (found version \"${NGHTTP3_VERSION}\")")
else()
find_path(NGHTTP3_INCLUDE_DIR NAMES "nghttp3/nghttp3.h")
find_library(NGHTTP3_LIBRARY NAMES "nghttp3")
mark_as_advanced(NGHTTP3_INCLUDE_DIR NGHTTP3_LIBRARY)
unset(NGHTTP3_VERSION CACHE)
if(NGHTTP3_INCLUDE_DIR AND EXISTS "${NGHTTP3_INCLUDE_DIR}/nghttp3/version.h")
set(_version_regex "#[\t ]*define[\t ]+NGHTTP3_VERSION[\t ]+\"([^\"]*)\"")
file(STRINGS "${NGHTTP3_INCLUDE_DIR}/nghttp3/version.h" _version_str REGEX "${_version_regex}")
string(REGEX REPLACE "${_version_regex}" "\\1" _version_str "${_version_str}")
set(NGHTTP3_VERSION "${_version_str}")
unset(_version_regex)
unset(_version_str)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(NGHTTP3
REQUIRED_VARS
NGHTTP3_INCLUDE_DIR
NGHTTP3_LIBRARY
VERSION_VAR
NGHTTP3_VERSION
)
if(NGHTTP3_FOUND)
set(NGHTTP3_INCLUDE_DIRS ${NGHTTP3_INCLUDE_DIR})
set(NGHTTP3_LIBRARIES ${NGHTTP3_LIBRARY})
endif()
mark_as_advanced(NGHTTP3_INCLUDE_DIR NGHTTP3_LIBRARY)
endif()

View File

@@ -41,36 +41,11 @@
# - `NGTCP2_FOUND`: System has ngtcp2.
# - `NGTCP2_INCLUDE_DIRS`: The ngtcp2 include directories.
# - `NGTCP2_LIBRARIES`: The ngtcp2 library names.
# - `NGTCP2_LIBRARY_DIRS`: The ngtcp2 library directories.
# - `NGTCP2_PC_REQUIRES`: The ngtcp2 pkg-config packages.
# - `NGTCP2_CFLAGS`: Required compiler flags.
# - `NGTCP2_VERSION`: Version of ngtcp2.
if(CURL_USE_PKGCONFIG)
find_package(PkgConfig QUIET)
pkg_check_modules(PC_NGTCP2 "libngtcp2")
endif()
find_path(NGTCP2_INCLUDE_DIR NAMES "ngtcp2/ngtcp2.h"
HINTS
${PC_NGTCP2_INCLUDEDIR}
${PC_NGTCP2_INCLUDE_DIRS}
)
find_library(NGTCP2_LIBRARY NAMES "ngtcp2"
HINTS
${PC_NGTCP2_LIBDIR}
${PC_NGTCP2_LIBRARY_DIRS}
)
if(PC_NGTCP2_VERSION)
set(NGTCP2_VERSION ${PC_NGTCP2_VERSION})
elseif(NGTCP2_INCLUDE_DIR AND EXISTS "${NGTCP2_INCLUDE_DIR}/ngtcp2/version.h")
set(_version_regex "#[\t ]*define[\t ]+NGTCP2_VERSION[\t ]+\"([^\"]*)\"")
file(STRINGS "${NGTCP2_INCLUDE_DIR}/ngtcp2/version.h" _version_str REGEX "${_version_regex}")
string(REGEX REPLACE "${_version_regex}" "\\1" _version_str "${_version_str}")
set(NGTCP2_VERSION "${_version_str}")
unset(_version_regex)
unset(_version_str)
endif()
if(NGTCP2_FIND_COMPONENTS)
set(_ngtcp2_crypto_backend "")
foreach(_component IN LISTS NGTCP2_FIND_COMPONENTS)
@@ -83,40 +58,73 @@ if(NGTCP2_FIND_COMPONENTS)
endforeach()
if(_ngtcp2_crypto_backend)
string(TOLOWER "ngtcp2_crypto_${_ngtcp2_crypto_backend}" _crypto_library)
if(CURL_USE_PKGCONFIG)
pkg_check_modules(PC_${_crypto_library} "lib${_crypto_library}")
endif()
get_filename_component(_ngtcp2_library_dir "${NGTCP2_LIBRARY}" DIRECTORY)
find_library(${_crypto_library}_LIBRARY NAMES ${_crypto_library}
HINTS
${_ngtcp2_library_dir}
${PC_${_crypto_library}_LIBDIR}
${PC_${_crypto_library}_LIBRARY_DIRS}
)
if(${_crypto_library}_LIBRARY)
set(NGTCP2_${_ngtcp2_crypto_backend}_FOUND TRUE)
set(NGTCP2_CRYPTO_LIBRARY ${${_crypto_library}_LIBRARY})
endif()
string(TOLOWER "ngtcp2_crypto_${_ngtcp2_crypto_backend}" _crypto_library_lower)
string(TOUPPER "ngtcp2_crypto_${_ngtcp2_crypto_backend}" _crypto_library_upper)
endif()
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(NGTCP2
REQUIRED_VARS
NGTCP2_INCLUDE_DIR
NGTCP2_LIBRARY
VERSION_VAR
NGTCP2_VERSION
HANDLE_COMPONENTS
)
if(NGTCP2_FOUND)
set(NGTCP2_INCLUDE_DIRS ${NGTCP2_INCLUDE_DIR})
set(NGTCP2_LIBRARIES ${NGTCP2_LIBRARY} ${NGTCP2_CRYPTO_LIBRARY})
set(NGTCP2_PC_REQUIRES "libngtcp2")
if(_ngtcp2_crypto_backend)
set(NGTCP2_CRYPTO_PC_REQUIRES "lib${_crypto_library_lower}")
endif()
mark_as_advanced(NGTCP2_INCLUDE_DIR NGTCP2_LIBRARY NGTCP2_CRYPTO_LIBRARY)
if(CURL_USE_PKGCONFIG AND
NOT DEFINED NGTCP2_INCLUDE_DIR AND
NOT DEFINED NGTCP2_LIBRARY)
find_package(PkgConfig QUIET)
pkg_check_modules(NGTCP2 ${NGTCP2_PC_REQUIRES})
if(_ngtcp2_crypto_backend)
pkg_check_modules("${_crypto_library_upper}" ${NGTCP2_CRYPTO_PC_REQUIRES})
else()
set("${_crypto_library_upper}_FOUND" TRUE)
endif()
endif()
list(APPEND NGTCP2_PC_REQUIRES ${NGTCP2_CRYPTO_PC_REQUIRES})
if(NGTCP2_FOUND AND "${${_crypto_library_upper}_FOUND}")
list(APPEND NGTCP2_LIBRARIES "${${_crypto_library_upper}_LIBRARIES}")
list(REMOVE_DUPLICATES NGTCP2_LIBRARIES)
string(REPLACE ";" " " NGTCP2_CFLAGS "${NGTCP2_CFLAGS}")
message(STATUS "Found NGTCP2 (via pkg-config): ${NGTCP2_INCLUDE_DIRS} (found version \"${NGTCP2_VERSION}\")")
else()
find_path(NGTCP2_INCLUDE_DIR NAMES "ngtcp2/ngtcp2.h")
find_library(NGTCP2_LIBRARY NAMES "ngtcp2")
unset(NGTCP2_VERSION CACHE)
if(NGTCP2_INCLUDE_DIR AND EXISTS "${NGTCP2_INCLUDE_DIR}/ngtcp2/version.h")
set(_version_regex "#[\t ]*define[\t ]+NGTCP2_VERSION[\t ]+\"([^\"]*)\"")
file(STRINGS "${NGTCP2_INCLUDE_DIR}/ngtcp2/version.h" _version_str REGEX "${_version_regex}")
string(REGEX REPLACE "${_version_regex}" "\\1" _version_str "${_version_str}")
set(NGTCP2_VERSION "${_version_str}")
unset(_version_regex)
unset(_version_str)
endif()
if(_ngtcp2_crypto_backend)
get_filename_component(_ngtcp2_library_dir "${NGTCP2_LIBRARY}" DIRECTORY)
find_library(${_crypto_library_upper}_LIBRARY NAMES ${_crypto_library_lower} HINTS ${_ngtcp2_library_dir})
if(${_crypto_library_upper}_LIBRARY)
set(NGTCP2_${_ngtcp2_crypto_backend}_FOUND TRUE)
set(NGTCP2_CRYPTO_LIBRARY ${${_crypto_library_upper}_LIBRARY})
endif()
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(NGTCP2
REQUIRED_VARS
NGTCP2_INCLUDE_DIR
NGTCP2_LIBRARY
VERSION_VAR
NGTCP2_VERSION
HANDLE_COMPONENTS
)
if(NGTCP2_FOUND)
set(NGTCP2_INCLUDE_DIRS ${NGTCP2_INCLUDE_DIR})
set(NGTCP2_LIBRARIES ${NGTCP2_LIBRARY} ${NGTCP2_CRYPTO_LIBRARY})
endif()
mark_as_advanced(NGTCP2_INCLUDE_DIR NGTCP2_LIBRARY NGTCP2_CRYPTO_LIBRARY)
endif()

View File

@@ -34,14 +34,17 @@
# - `NETTLE_INCLUDE_DIRS`: The nettle include directories.
# - `NETTLE_LIBRARIES`: The nettle library names.
# - `NETTLE_LIBRARY_DIRS`: The nettle library directories.
# - `NETTLE_PC_REQUIRES`: The nettle pkg-config packages.
# - `NETTLE_CFLAGS`: Required compiler flags.
# - `NETTLE_VERSION`: Version of nettle.
set(NETTLE_PC_REQUIRES "nettle")
if(CURL_USE_PKGCONFIG AND
NOT DEFINED NETTLE_INCLUDE_DIR AND
NOT DEFINED NETTLE_LIBRARY)
find_package(PkgConfig QUIET)
pkg_check_modules(NETTLE "nettle")
pkg_check_modules(NETTLE ${NETTLE_PC_REQUIRES})
endif()
if(NETTLE_FOUND)

View File

@@ -34,14 +34,17 @@
# - `QUICHE_INCLUDE_DIRS`: The quiche include directories.
# - `QUICHE_LIBRARIES`: The quiche library names.
# - `QUICHE_LIBRARY_DIRS`: The quiche library directories.
# - `QUICHE_PC_REQUIRES`: The quiche pkg-config packages.
# - `QUICHE_CFLAGS`: Required compiler flags.
# - `QUICHE_VERSION`: Version of quiche.
set(QUICHE_PC_REQUIRES "quiche")
if(CURL_USE_PKGCONFIG AND
NOT DEFINED QUICHE_INCLUDE_DIR AND
NOT DEFINED QUICHE_LIBRARY)
find_package(PkgConfig QUIET)
pkg_check_modules(QUICHE "quiche")
pkg_check_modules(QUICHE ${QUICHE_PC_REQUIRES})
endif()
if(QUICHE_FOUND)

View File

@@ -38,18 +38,21 @@
# - `RUSTLS_CFLAGS`: Required compiler flags.
# - `RUSTLS_VERSION`: Version of Rustls.
set(RUSTLS_PC_REQUIRES "rustls")
if(CURL_USE_PKGCONFIG AND
NOT DEFINED RUSTLS_INCLUDE_DIR AND
NOT DEFINED RUSTLS_LIBRARY)
find_package(PkgConfig QUIET)
pkg_check_modules(RUSTLS "rustls")
pkg_check_modules(RUSTLS ${RUSTLS_PC_REQUIRES})
endif()
if(RUSTLS_FOUND)
set(RUSTLS_PC_REQUIRES "rustls")
string(REPLACE ";" " " RUSTLS_CFLAGS "${RUSTLS_CFLAGS}")
message(STATUS "Found Rustls (via pkg-config): ${RUSTLS_INCLUDE_DIRS} (found version \"${RUSTLS_VERSION}\")")
else()
set(RUSTLS_PC_REQUIRES "") # Depend on pkg-config only when found via pkg-config
find_path(RUSTLS_INCLUDE_DIR NAMES "rustls.h")
find_library(RUSTLS_LIBRARY NAMES "rustls")
@@ -68,36 +71,38 @@ else()
mark_as_advanced(RUSTLS_INCLUDE_DIR RUSTLS_LIBRARY)
endif()
if(APPLE)
find_library(SECURITY_FRAMEWORK "Security")
mark_as_advanced(SECURITY_FRAMEWORK)
if(NOT SECURITY_FRAMEWORK)
message(FATAL_ERROR "Security framework not found")
endif()
list(APPEND RUSTLS_LIBRARIES "-framework Security")
if(RUSTLS_FOUND)
if(APPLE)
find_library(SECURITY_FRAMEWORK NAMES "Security")
mark_as_advanced(SECURITY_FRAMEWORK)
if(NOT SECURITY_FRAMEWORK)
message(FATAL_ERROR "Security framework not found")
endif()
list(APPEND RUSTLS_LIBRARIES "-framework Security")
find_library(FOUNDATION_FRAMEWORK "Foundation")
mark_as_advanced(FOUNDATION_FRAMEWORK)
if(NOT FOUNDATION_FRAMEWORK)
message(FATAL_ERROR "Foundation framework not found")
endif()
list(APPEND RUSTLS_LIBRARIES "-framework Foundation")
elseif(NOT WIN32)
find_library(_pthread_library "pthread")
if(_pthread_library)
list(APPEND RUSTLS_LIBRARIES "pthread")
endif()
mark_as_advanced(_pthread_library)
find_library(FOUNDATION_FRAMEWORK NAMES "Foundation")
mark_as_advanced(FOUNDATION_FRAMEWORK)
if(NOT FOUNDATION_FRAMEWORK)
message(FATAL_ERROR "Foundation framework not found")
endif()
list(APPEND RUSTLS_LIBRARIES "-framework Foundation")
elseif(NOT WIN32)
find_library(PTHREAD_LIBRARY NAMES "pthread")
if(PTHREAD_LIBRARY)
list(APPEND RUSTLS_LIBRARIES ${PTHREAD_LIBRARY})
endif()
mark_as_advanced(PTHREAD_LIBRARY)
find_library(_dl_library "dl")
if(_dl_library)
list(APPEND RUSTLS_LIBRARIES "dl")
endif()
mark_as_advanced(_dl_library)
find_library(DL_LIBRARY NAMES "dl")
if(DL_LIBRARY)
list(APPEND RUSTLS_LIBRARIES ${DL_LIBRARY})
endif()
mark_as_advanced(DL_LIBRARY)
find_library(_math_library "m")
if(_math_library)
list(APPEND RUSTLS_LIBRARIES "m")
find_library(MATH_LIBRARY NAMES "m")
if(MATH_LIBRARY)
list(APPEND RUSTLS_LIBRARIES ${MATH_LIBRARY})
endif()
mark_as_advanced(MATH_LIBRARY)
endif()
mark_as_advanced(_math_library)
endif()

View File

@@ -34,6 +34,7 @@
# - `WOLFSSL_INCLUDE_DIRS`: The wolfSSL include directories.
# - `WOLFSSL_LIBRARIES`: The wolfSSL library names.
# - `WOLFSSL_LIBRARY_DIRS`: The wolfSSL library directories.
# - `WOLFSSL_PC_REQUIRES`: The wolfSSL pkg-config packages.
# - `WOLFSSL_CFLAGS`: Required compiler flags.
# - `WOLFSSL_VERSION`: Version of wolfSSL.
@@ -46,11 +47,13 @@ if(DEFINED WolfSSL_LIBRARY AND NOT DEFINED WOLFSSL_LIBRARY)
set(WOLFSSL_LIBRARY "${WolfSSL_LIBRARY}")
endif()
set(WOLFSSL_PC_REQUIRES "wolfssl")
if(CURL_USE_PKGCONFIG AND
NOT DEFINED WOLFSSL_INCLUDE_DIR AND
NOT DEFINED WOLFSSL_LIBRARY)
find_package(PkgConfig QUIET)
pkg_check_modules(WOLFSSL "wolfssl")
pkg_check_modules(WOLFSSL ${WOLFSSL_PC_REQUIRES})
endif()
if(WOLFSSL_FOUND)
@@ -87,10 +90,10 @@ else()
mark_as_advanced(WOLFSSL_INCLUDE_DIR WOLFSSL_LIBRARY)
endif()
if(NOT WIN32)
find_library(_math_library "m")
if(_math_library)
list(APPEND WOLFSSL_LIBRARIES "m") # for log and pow
if(WOLFSSL_FOUND AND NOT WIN32)
find_library(MATH_LIBRARY NAMES "m")
if(MATH_LIBRARY)
list(APPEND WOLFSSL_LIBRARIES ${MATH_LIBRARY}) # for log and pow
endif()
mark_as_advanced(_math_library)
mark_as_advanced(MATH_LIBRARY)
endif()

View File

@@ -33,6 +33,9 @@
# - `ZSTD_FOUND`: System has zstd.
# - `ZSTD_INCLUDE_DIRS`: The zstd include directories.
# - `ZSTD_LIBRARIES`: The zstd library names.
# - `ZSTD_LIBRARY_DIRS`: The zstd library directories.
# - `ZSTD_PC_REQUIRES`: The zstd pkg-config packages.
# - `ZSTD_CFLAGS`: Required compiler flags.
# - `ZSTD_VERSION`: Version of zstd.
if(DEFINED Zstd_INCLUDE_DIR AND NOT DEFINED ZSTD_INCLUDE_DIR)
@@ -44,56 +47,55 @@ if(DEFINED Zstd_LIBRARY AND NOT DEFINED ZSTD_LIBRARY)
set(ZSTD_LIBRARY "${Zstd_LIBRARY}")
endif()
if(CURL_USE_PKGCONFIG)
set(ZSTD_PC_REQUIRES "libzstd")
if(CURL_USE_PKGCONFIG AND
NOT DEFINED ZSTD_INCLUDE_DIR AND
NOT DEFINED ZSTD_LIBRARY)
find_package(PkgConfig QUIET)
pkg_check_modules(PC_ZSTD "libzstd")
pkg_check_modules(ZSTD ${ZSTD_PC_REQUIRES})
endif()
find_path(ZSTD_INCLUDE_DIR NAMES "zstd.h"
HINTS
${PC_ZSTD_INCLUDEDIR}
${PC_ZSTD_INCLUDE_DIRS}
)
find_library(ZSTD_LIBRARY NAMES "zstd"
HINTS
${PC_ZSTD_LIBDIR}
${PC_ZSTD_LIBRARY_DIRS}
)
if(PC_ZSTD_VERSION)
set(ZSTD_VERSION ${PC_ZSTD_VERSION})
elseif(ZSTD_INCLUDE_DIR AND EXISTS "${ZSTD_INCLUDE_DIR}/zstd.h")
set(_version_regex1 "#[\t ]*define[ \t]+ZSTD_VERSION_MAJOR[ \t]+([0-9]+).*")
set(_version_regex2 "#[\t ]*define[ \t]+ZSTD_VERSION_MINOR[ \t]+([0-9]+).*")
set(_version_regex3 "#[\t ]*define[ \t]+ZSTD_VERSION_RELEASE[ \t]+([0-9]+).*")
file(STRINGS "${ZSTD_INCLUDE_DIR}/zstd.h" _version_str1 REGEX "${_version_regex1}")
file(STRINGS "${ZSTD_INCLUDE_DIR}/zstd.h" _version_str2 REGEX "${_version_regex2}")
file(STRINGS "${ZSTD_INCLUDE_DIR}/zstd.h" _version_str3 REGEX "${_version_regex3}")
string(REGEX REPLACE "${_version_regex1}" "\\1" _version_str1 "${_version_str1}")
string(REGEX REPLACE "${_version_regex2}" "\\1" _version_str2 "${_version_str2}")
string(REGEX REPLACE "${_version_regex3}" "\\1" _version_str3 "${_version_str3}")
set(ZSTD_VERSION "${_version_str1}.${_version_str2}.${_version_str3}")
unset(_version_regex1)
unset(_version_regex2)
unset(_version_regex3)
unset(_version_str1)
unset(_version_str2)
unset(_version_str3)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Zstd
REQUIRED_VARS
ZSTD_INCLUDE_DIR
ZSTD_LIBRARY
VERSION_VAR
ZSTD_VERSION
)
if(ZSTD_FOUND)
set(ZSTD_INCLUDE_DIRS ${ZSTD_INCLUDE_DIR})
set(ZSTD_LIBRARIES ${ZSTD_LIBRARY})
endif()
string(REPLACE ";" " " ZSTD_CFLAGS "${ZSTD_CFLAGS}")
message(STATUS "Found Zstd (via pkg-config): ${ZSTD_INCLUDE_DIRS} (found version \"${ZSTD_VERSION}\")")
else()
find_path(ZSTD_INCLUDE_DIR NAMES "zstd.h")
find_library(ZSTD_LIBRARY NAMES "zstd")
mark_as_advanced(ZSTD_INCLUDE_DIR ZSTD_LIBRARY)
unset(ZSTD_VERSION CACHE)
if(ZSTD_INCLUDE_DIR AND EXISTS "${ZSTD_INCLUDE_DIR}/zstd.h")
set(_version_regex1 "#[\t ]*define[ \t]+ZSTD_VERSION_MAJOR[ \t]+([0-9]+).*")
set(_version_regex2 "#[\t ]*define[ \t]+ZSTD_VERSION_MINOR[ \t]+([0-9]+).*")
set(_version_regex3 "#[\t ]*define[ \t]+ZSTD_VERSION_RELEASE[ \t]+([0-9]+).*")
file(STRINGS "${ZSTD_INCLUDE_DIR}/zstd.h" _version_str1 REGEX "${_version_regex1}")
file(STRINGS "${ZSTD_INCLUDE_DIR}/zstd.h" _version_str2 REGEX "${_version_regex2}")
file(STRINGS "${ZSTD_INCLUDE_DIR}/zstd.h" _version_str3 REGEX "${_version_regex3}")
string(REGEX REPLACE "${_version_regex1}" "\\1" _version_str1 "${_version_str1}")
string(REGEX REPLACE "${_version_regex2}" "\\1" _version_str2 "${_version_str2}")
string(REGEX REPLACE "${_version_regex3}" "\\1" _version_str3 "${_version_str3}")
set(ZSTD_VERSION "${_version_str1}.${_version_str2}.${_version_str3}")
unset(_version_regex1)
unset(_version_regex2)
unset(_version_regex3)
unset(_version_str1)
unset(_version_str2)
unset(_version_str3)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Zstd
REQUIRED_VARS
ZSTD_INCLUDE_DIR
ZSTD_LIBRARY
VERSION_VAR
ZSTD_VERSION
)
if(ZSTD_FOUND)
set(ZSTD_INCLUDE_DIRS ${ZSTD_INCLUDE_DIR})
set(ZSTD_LIBRARIES ${ZSTD_LIBRARY})
endif()
mark_as_advanced(ZSTD_INCLUDE_DIR ZSTD_LIBRARY)
endif()

View File

@@ -27,7 +27,7 @@
# This macro is intended to be called multiple times with a sequence of
# possibly dependent header files. Some headers depend on others to be
# compiled correctly.
macro(check_include_file_concat _file _variable)
macro(check_include_file_concat_curl _file _variable)
check_include_files("${CURL_INCLUDES};${_file}" ${_variable})
if(${_variable})
list(APPEND CURL_INCLUDES ${_file})
@@ -62,21 +62,25 @@ macro(curl_internal_test _curl_test)
endif()
endmacro()
macro(curl_dependency_option _dependency)
set(CURL_${_dependency} "AUTO" CACHE STRING "Build curl with ${_dependency} support (AUTO, ON or OFF)")
set_property(CACHE CURL_${_dependency} PROPERTY STRINGS "AUTO" "ON" "OFF")
macro(curl_dependency_option _option_name _find_name _desc_name)
set(${_option_name} "AUTO" CACHE STRING "Build curl with ${_desc_name} support (AUTO, ON or OFF)")
set_property(CACHE ${_option_name} PROPERTY STRINGS "AUTO" "ON" "OFF")
if(CURL_${_dependency} STREQUAL "AUTO")
find_package(${_dependency})
elseif(CURL_${_dependency})
find_package(${_dependency} REQUIRED)
if(${_option_name} STREQUAL "AUTO")
find_package(${_find_name})
elseif(${_option_name})
find_package(${_find_name} REQUIRED)
endif()
endmacro()
# Convert the passed paths to libpath linker options and add them to CMAKE_REQUIRED_LINK_OPTIONS.
# Convert the passed paths to libpath linker options and add them to CMAKE_REQUIRED_*.
macro(curl_required_libpaths _libpaths_arg)
set(_libpaths "${_libpaths_arg}")
foreach(_libpath IN LISTS _libpaths)
list(APPEND CMAKE_REQUIRED_LINK_OPTIONS "${CMAKE_LIBRARY_PATH_FLAG}${_libpath}")
endforeach()
if(CMAKE_VERSION VERSION_LESS 3.31)
set(_libpaths "${_libpaths_arg}")
foreach(_libpath IN LISTS _libpaths)
list(APPEND CMAKE_REQUIRED_LINK_OPTIONS "${CMAKE_LIBRARY_PATH_FLAG}${_libpath}")
endforeach()
else()
list(APPEND CMAKE_REQUIRED_LINK_DIRECTORIES "${_libpaths_arg}")
endif()
endmacro()

View File

@@ -25,7 +25,7 @@ include(CheckCSourceCompiles)
include(CheckCSourceRuns)
include(CheckTypeSize)
macro(add_header_include _check _header)
macro(curl_add_header_include _check _header)
if(${_check})
set(_source_epilogue "${_source_epilogue}
#include <${_header}>")
@@ -37,10 +37,10 @@ set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")
if(NOT DEFINED HAVE_STRUCT_SOCKADDR_STORAGE)
cmake_push_check_state()
unset(CMAKE_EXTRA_INCLUDE_FILES)
set(CMAKE_EXTRA_INCLUDE_FILES "")
if(WIN32)
set(CMAKE_EXTRA_INCLUDE_FILES "winsock2.h")
set(CMAKE_REQUIRED_LIBRARIES "ws2_32")
list(APPEND CMAKE_REQUIRED_LIBRARIES "ws2_32")
elseif(HAVE_SYS_SOCKET_H)
set(CMAKE_EXTRA_INCLUDE_FILES "sys/socket.h")
endif()
@@ -51,8 +51,8 @@ endif()
if(NOT WIN32)
set(_source_epilogue "#undef inline")
add_header_include(HAVE_SYS_TYPES_H "sys/types.h")
add_header_include(HAVE_SYS_SOCKET_H "sys/socket.h")
curl_add_header_include(HAVE_SYS_TYPES_H "sys/types.h")
curl_add_header_include(HAVE_SYS_SOCKET_H "sys/socket.h")
check_c_source_compiles("${_source_epilogue}
int main(void)
{
@@ -63,7 +63,7 @@ if(NOT WIN32)
endif()
set(_source_epilogue "#undef inline")
add_header_include(HAVE_SYS_TIME_H "sys/time.h")
curl_add_header_include(HAVE_SYS_TIME_H "sys/time.h")
check_c_source_compiles("${_source_epilogue}
#include <time.h>
int main(void)
@@ -98,9 +98,9 @@ endif()
if(NOT DEFINED HAVE_GETADDRINFO_THREADSAFE)
set(_source_epilogue "#undef inline")
add_header_include(HAVE_SYS_SOCKET_H "sys/socket.h")
add_header_include(HAVE_SYS_TIME_H "sys/time.h")
add_header_include(HAVE_NETDB_H "netdb.h")
curl_add_header_include(HAVE_SYS_SOCKET_H "sys/socket.h")
curl_add_header_include(HAVE_SYS_TIME_H "sys/time.h")
curl_add_header_include(HAVE_NETDB_H "netdb.h")
check_c_source_compiles("${_source_epilogue}
int main(void)
{
@@ -141,8 +141,8 @@ endif()
if(NOT WIN32 AND NOT DEFINED HAVE_CLOCK_GETTIME_MONOTONIC_RAW)
set(_source_epilogue "#undef inline")
add_header_include(HAVE_SYS_TYPES_H "sys/types.h")
add_header_include(HAVE_SYS_TIME_H "sys/time.h")
curl_add_header_include(HAVE_SYS_TYPES_H "sys/types.h")
curl_add_header_include(HAVE_SYS_TIME_H "sys/time.h")
check_c_source_compiles("${_source_epilogue}
#include <time.h>
int main(void)

View File

@@ -23,17 +23,15 @@
###########################################################################
include(CheckCCompilerFlag)
unset(_picky)
set(_picky "")
if(CURL_WERROR AND
((CMAKE_COMPILER_IS_GNUCC AND
NOT DOS AND # Watt-32 headers use the '#include_next' GCC extension
NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 5.0 AND
NOT CMAKE_VERSION VERSION_LESS 3.23.0) OR # to avoid check_symbol_exists() conflicting with GCC -pedantic-errors
CMAKE_C_COMPILER_ID MATCHES "Clang"))
list(APPEND _picky "-pedantic-errors")
if(MSVC) # clang-cl
list(APPEND _picky "-Wno-language-extension-token") # Override default error to make __int64 size detection pass
endif()
endif()
if(APPLE AND
@@ -77,7 +75,6 @@ if(PICKY_COMPILER)
list(APPEND _picky_enable
-Wbad-function-cast # clang 2.7 gcc 2.95
-Wconversion # clang 2.7 gcc 2.95
-Winline # clang 1.0 gcc 1.0
-Wmissing-declarations # clang 1.0 gcc 2.7
-Wmissing-prototypes # clang 1.0 gcc 1.0
-Wnested-externs # clang 1.0 gcc 2.7
@@ -106,12 +103,11 @@ if(PICKY_COMPILER)
-Wmissing-field-initializers # clang 2.7 gcc 4.1
-Wmissing-noreturn # clang 2.7 gcc 4.1
-Wno-format-nonliteral # clang 1.0 gcc 2.96 (3.0)
-Wno-sign-conversion # clang 2.9 gcc 4.3
-Wno-system-headers # clang 1.0 gcc 3.0
# -Wpadded # clang 2.9 gcc 4.1 # Not used: We cannot change public structs
-Wold-style-definition # clang 2.7 gcc 3.4
-Wredundant-decls # clang 2.7 gcc 4.1
-Wsign-conversion # clang 2.9 gcc 4.3
-Wno-error=sign-conversion # FIXME
-Wstrict-prototypes # clang 1.0 gcc 3.3
# -Wswitch-enum # clang 2.7 gcc 4.1 # Not used: It basically disallows default case
-Wtype-limits # clang 2.7 gcc 4.3
@@ -121,13 +117,6 @@ if(PICKY_COMPILER)
-Wvla # clang 2.8 gcc 4.3
)
set(_picky_common
-Wdouble-promotion # clang 3.6 gcc 4.6 appleclang 6.3
-Wenum-conversion # clang 3.2 gcc 10.0 appleclang 4.6 g++ 11.0
-Wpragmas # clang 3.5 gcc 4.1 appleclang 6.0
-Wunused-const-variable # clang 3.4 gcc 6.0 appleclang 5.1
)
if(CMAKE_C_COMPILER_ID MATCHES "Clang")
list(APPEND _picky_enable
${_picky_common_old}
@@ -137,17 +126,20 @@ if(PICKY_COMPILER)
)
if(NOT MSVC)
list(APPEND _picky_enable
-Wlanguage-extension-token # clang 3.0 # Avoid for clang-cl to allow __int64
-Wlanguage-extension-token # clang 3.0
)
endif()
# Enable based on compiler version
if((CMAKE_C_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.6) OR
(CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 6.3))
list(APPEND _picky_enable
${_picky_common}
# -Wunreachable-code-break # clang 3.5 appleclang 6.0 # Not used: Silent in "unity" builds
-Wdouble-promotion # clang 3.6 gcc 4.6 appleclang 6.3
-Wenum-conversion # clang 3.2 gcc 10.0 appleclang 4.6 g++ 11.0
-Wheader-guard # clang 3.4 appleclang 5.1
-Wpragmas # clang 3.5 gcc 4.1 appleclang 6.0
-Wsometimes-uninitialized # clang 3.2 appleclang 4.6
# -Wunreachable-code-break # clang 3.5 appleclang 6.0 # Not used: Silent in "unity" builds
-Wunused-const-variable # clang 3.4 gcc 6.0 appleclang 5.1
)
endif()
if((CMAKE_C_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.9) OR
@@ -171,9 +163,6 @@ if(PICKY_COMPILER)
)
endif()
else() # gcc
list(APPEND _picky_detect
${_picky_common}
)
# Enable based on compiler version
if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.3)
list(APPEND _picky_enable
@@ -181,8 +170,8 @@ if(PICKY_COMPILER)
-Wclobbered # gcc 4.3
-Wmissing-parameter-type # gcc 4.3
-Wold-style-declaration # gcc 4.3
-Wpragmas # clang 3.5 gcc 4.1 appleclang 6.0
-Wstrict-aliasing=3 # gcc 4.0
-Wtrampolines # gcc 4.3
)
endif()
if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.5 AND MINGW)
@@ -192,7 +181,9 @@ if(PICKY_COMPILER)
endif()
if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.8)
list(APPEND _picky_enable
-Wdouble-promotion # clang 3.6 gcc 4.6 appleclang 6.3
-Wformat=2 # clang 3.0 gcc 4.8
-Wtrampolines # gcc 4.6
)
endif()
if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 5.0)
@@ -207,6 +198,7 @@ if(PICKY_COMPILER)
-fdelete-null-pointer-checks
-Wshift-negative-value # clang 3.7 gcc 6.0 (clang default)
-Wshift-overflow=2 # clang 3.0 gcc 6.0 (clang default: -Wshift-overflow)
-Wunused-const-variable # clang 3.4 gcc 6.0 appleclang 5.1
)
endif()
if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 7.0)
@@ -221,6 +213,7 @@ if(PICKY_COMPILER)
if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 10.0)
list(APPEND _picky_enable
-Warith-conversion # gcc 10.0
-Wenum-conversion # clang 3.2 gcc 10.0 appleclang 4.6 g++ 11.0
)
endif()
endif()
@@ -242,20 +235,41 @@ if(PICKY_COMPILER)
list(APPEND _picky "${_ccopt}")
endif()
endforeach()
if(CMAKE_COMPILER_IS_GNUCC)
if(CMAKE_C_COMPILER_VERSION VERSION_LESS 4.5)
# Avoid false positives
list(APPEND _picky "-Wno-shadow")
list(APPEND _picky "-Wno-unreachable-code")
endif()
if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.2 AND CMAKE_C_COMPILER_VERSION VERSION_LESS 4.6)
# GCC <4.6 do not support #pragma to suppress warnings locally. Disable them globally instead.
list(APPEND _picky "-Wno-overlength-strings")
endif()
if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.0 AND CMAKE_C_COMPILER_VERSION VERSION_LESS 4.7)
list(APPEND _picky "-Wno-missing-field-initializers") # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36750
endif()
if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.3 AND CMAKE_C_COMPILER_VERSION VERSION_LESS 4.8)
list(APPEND _picky "-Wno-type-limits") # Avoid false positives
endif()
endif()
endif()
endif()
# clang-cl
if(CMAKE_C_COMPILER_ID STREQUAL "Clang" AND MSVC)
if(CMAKE_VERSION VERSION_LESS 3.12)
set(_picky_tmp "")
foreach(_ccopt IN LISTS _picky)
list(APPEND _picky_tmp "/clang:${_ccopt}")
endforeach()
set(_picky ${_picky_tmp})
else()
list(TRANSFORM _picky PREPEND "/clang:")
endif()
list(APPEND _picky "-Wno-language-extension-token") # Allow __int64
set(_picky_tmp "")
foreach(_ccopt IN LISTS _picky)
# Prefix -Wall, otherwise clang-cl interprets it as an MSVC option and translates it to -Weverything
if(_ccopt MATCHES "^-W" AND NOT _ccopt STREQUAL "-Wall")
list(APPEND _picky_tmp ${_ccopt})
else()
list(APPEND _picky_tmp "-clang:${_ccopt}")
endif()
endforeach()
set(_picky ${_picky_tmp})
endif()
if(_picky)

View File

@@ -23,13 +23,31 @@
###########################################################################
# File containing various utilities
# Returns number of arguments that evaluate to true
function(count_true _output_count_var)
set(lst_len 0)
foreach(option_var IN LISTS ARGN)
if(${option_var})
math(EXPR lst_len "${lst_len} + 1")
# Return number of arguments that evaluate to true
function(curl_count_true _output_count_var)
set(_list_len 0)
foreach(_option_var IN LISTS ARGN)
if(${_option_var})
math(EXPR _list_len "${_list_len} + 1")
endif()
endforeach()
set(${_output_count_var} ${lst_len} PARENT_SCOPE)
set(${_output_count_var} ${_list_len} PARENT_SCOPE)
endfunction()
# Dump all defined variables with their values
function(curl_dumpvars)
message("::group::CMake Variable Dump")
get_cmake_property(_vars VARIABLES)
foreach(_var IN ITEMS ${_vars})
get_property(_var_type CACHE ${_var} PROPERTY TYPE)
get_property(_var_advanced CACHE ${_var} PROPERTY ADVANCED)
if(_var_type)
set(_var_type ":${_var_type}")
endif()
if(_var_advanced)
set(_var_advanced " [adv]")
endif()
message("${_var}${_var_type}${_var_advanced} = ${${_var}}")
endforeach()
message("::endgroup::")
endfunction()

View File

@@ -23,13 +23,6 @@
###########################################################################
@PACKAGE_INIT@
if(UNIX OR VCPKG_TOOLCHAIN OR (MINGW AND NOT CMAKE_CROSSCOMPILING)) # Keep in sync with root CMakeLists.txt
set(_curl_use_pkgconfig_default ON)
else()
set(_curl_use_pkgconfig_default OFF)
endif()
option(CURL_USE_PKGCONFIG "Enable pkg-config to detect @PROJECT_NAME@ dependencies" ${_curl_use_pkgconfig_default})
include(CMakeFindDependencyMacro)
if("@USE_OPENSSL@")
find_dependency(OpenSSL "@OPENSSL_VERSION_MAJOR@")
@@ -39,7 +32,6 @@ if("@HAVE_LIBZ@")
endif()
include("${CMAKE_CURRENT_LIST_DIR}/@TARGETS_EXPORT_NAME@.cmake")
check_required_components("@PROJECT_NAME@")
# Alias for either shared or static library
if(NOT TARGET @PROJECT_NAME@::libcurl)
@@ -47,5 +39,32 @@ if(NOT TARGET @PROJECT_NAME@::libcurl)
endif()
# For compatibility with CMake's FindCURL.cmake
set(CURL_VERSION_STRING "@CURLVERSION@")
set(CURL_LIBRARIES @PROJECT_NAME@::libcurl)
set_and_check(CURL_INCLUDE_DIRS "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@")
set(CURL_SUPPORTED_PROTOCOLS "@CURL_SUPPORTED_PROTOCOLS_LIST@")
set(CURL_SUPPORTED_FEATURES "@CURL_SUPPORTED_FEATURES_LIST@")
foreach(_item IN LISTS CURL_SUPPORTED_PROTOCOLS CURL_SUPPORTED_FEATURES)
set(CURL_SUPPORTS_${_item} TRUE)
endforeach()
set(_missing_req "")
foreach(_item IN LISTS CURL_FIND_COMPONENTS)
if(CURL_SUPPORTS_${_item})
set(CURL_${_item}_FOUND TRUE)
elseif(CURL_FIND_REQUIRED_${_item})
list(APPEND _missing_req ${_item})
endif()
endforeach()
if(_missing_req)
string(REPLACE ";" " " _missing_req "${_missing_req}")
if(CURL_FIND_REQUIRED)
message(FATAL_ERROR "CURL: missing required components: ${_missing_req}")
endif()
unset(_missing_req)
endif()
check_required_components("@PROJECT_NAME@")

View File

@@ -32,11 +32,11 @@ if(MINGW)
set(HAVE_UNISTD_H 1)
set(HAVE_LIBGEN_H 1)
set(HAVE_STDDEF_H 1) # detected by CMake internally in check_type_size()
set(HAVE_STDINT_H 1) # detected by CMake internally in check_type_size()
set(HAVE_STDBOOL_H 1)
set(HAVE_BOOL_T "${HAVE_STDBOOL_H}")
set(HAVE_STRTOLL 1)
set(HAVE_BASENAME 1)
set(HAVE_STRCASECMP 1)
set(HAVE_FTRUNCATE 1)
set(HAVE_SYS_PARAM_H 1)
set(HAVE_SYS_TIME_H 1)
@@ -45,9 +45,23 @@ if(MINGW)
set(HAVE_UTIME_H 1) # wrapper to sys/utime.h
set(HAVE_DIRENT_H 1)
set(HAVE_OPENDIR 1)
if(MINGW64_VERSION)
if(NOT MINGW64_VERSION VERSION_LESS 4.0)
set(HAVE_STRTOK_R 1)
else()
set(HAVE_STRTOK_R 0)
endif()
endif()
if((CMAKE_COMPILER_IS_GNUCC AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.9) OR
(CMAKE_C_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.6))
set(HAVE_STDATOMIC_H 1)
set(HAVE_ATOMIC 1)
else()
set(HAVE_STDATOMIC_H 0)
set(HAVE_ATOMIC 0)
endif()
else()
set(HAVE_LIBGEN_H 0)
set(HAVE_STRCASECMP 0)
set(HAVE_FTRUNCATE 0)
set(HAVE_SYS_PARAM_H 0)
set(HAVE_SYS_TIME_H 0)
@@ -58,9 +72,13 @@ else()
set(HAVE_OPENDIR 0)
if(MSVC)
set(HAVE_UNISTD_H 0)
set(HAVE_LOCALE_H 1)
set(HAVE_STDDEF_H 1) # detected by CMake internally in check_type_size()
set(HAVE_STDATOMIC_H 0)
if(NOT MSVC_VERSION LESS 1600)
set(HAVE_STDINT_H 1) # detected by CMake internally in check_type_size()
else()
set(HAVE_STDINT_H 0) # detected by CMake internally in check_type_size()
endif()
if(NOT MSVC_VERSION LESS 1800)
set(HAVE_STDBOOL_H 1)
set(HAVE_STRTOLL 1)
@@ -85,7 +103,6 @@ endif()
set(HAVE_GETADDRINFO 1)
set(HAVE_FREEADDRINFO 1)
set(HAVE_FCHMOD 0)
set(HAVE_SOCKETPAIR 0)
set(HAVE_SENDMSG 0)
set(HAVE_SENDMMSG 0)
@@ -112,10 +129,8 @@ set(HAVE_GETHOSTNAME 1)
set(HAVE_RECV 1)
set(HAVE_SEND 1)
set(HAVE_STROPTS_H 0)
set(HAVE_SYS_XATTR_H 0)
set(HAVE_ARC4RANDOM 0)
set(HAVE_FNMATCH 0)
set(HAVE_SCHED_YIELD 0)
set(HAVE_ARPA_INET_H 0)
set(HAVE_FCNTL_H 1)
set(HAVE_IFADDRS_H 0)
@@ -132,7 +147,6 @@ set(HAVE_POLL 0)
set(HAVE_PWD_H 0)
set(HAVE_SYS_EVENTFD_H 0)
set(HAVE_SYS_FILIO_H 0)
set(HAVE_SYS_WAIT_H 0)
set(HAVE_SYS_IOCTL_H 0)
set(HAVE_SYS_POLL_H 0)
set(HAVE_SYS_RESOURCE_H 0)
@@ -147,12 +161,9 @@ set(HAVE_TERMIOS_H 0)
set(HAVE_TERMIO_H 0)
set(HAVE_LINUX_TCP_H 0)
set(HAVE_FSEEKO 0) # mingw-w64 2.0.0 and newer has it
set(HAVE_SOCKET 1)
set(HAVE_SELECT 1)
set(HAVE_STRDUP 1)
set(HAVE_STRICMP 1)
set(HAVE_STRCMPI 1)
set(HAVE_MEMRCHR 0)
set(HAVE_CLOSESOCKET 1)
set(HAVE_SIGSETJMP 0)
@@ -178,6 +189,7 @@ set(HAVE_POSIX_STRERROR_R 0)
set(HAVE_MSG_NOSIGNAL 0)
set(HAVE_STRUCT_TIMEVAL 1)
set(HAVE_STRUCT_SOCKADDR_STORAGE 1)
set(HAVE_TIME_T_UNSIGNED 0)
set(HAVE_GETHOSTBYNAME_R_3 0)
set(HAVE_GETHOSTBYNAME_R_3_REENTRANT 0)
@@ -186,7 +198,6 @@ set(HAVE_GETHOSTBYNAME_R_5_REENTRANT 0)
set(HAVE_GETHOSTBYNAME_R_6 0)
set(HAVE_GETHOSTBYNAME_R_6_REENTRANT 0)
set(HAVE_O_NONBLOCK 0)
set(HAVE_IN_ADDR_T 0)
set(STDC_HEADERS 1)

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
COPYRIGHT AND PERMISSION NOTICE
Copyright (c) 1996 - 2024, Daniel Stenberg, <daniel@haxx.se>, and many
Copyright (c) 1996 - 2025, Daniel Stenberg, <daniel@haxx.se>, and many
contributors, see the THANKS file.
All rights reserved.

View File

@@ -1959,10 +1959,10 @@ typedef enum {
/* Set stream weight, 1 - 256 (default is 16) */
CURLOPT(CURLOPT_STREAM_WEIGHT, CURLOPTTYPE_LONG, 239),
/* Set stream dependency on another CURL handle */
/* Set stream dependency on another curl handle */
CURLOPT(CURLOPT_STREAM_DEPENDS, CURLOPTTYPE_OBJECTPOINT, 240),
/* Set E-xclusive stream dependency on another CURL handle */
/* Set E-xclusive stream dependency on another curl handle */
CURLOPT(CURLOPT_STREAM_DEPENDS_E, CURLOPTTYPE_OBJECTPOINT, 241),
/* Do not send any tftp option requests to the server */
@@ -2959,7 +2959,9 @@ typedef enum {
CURLINFO_USED_PROXY = CURLINFO_LONG + 66,
CURLINFO_POSTTRANSFER_TIME_T = CURLINFO_OFF_T + 67,
CURLINFO_EARLYDATA_SENT_T = CURLINFO_OFF_T + 68,
CURLINFO_LASTONE = 68
CURLINFO_HTTPAUTH_USED = CURLINFO_LONG + 69,
CURLINFO_PROXYAUTH_USED = CURLINFO_LONG + 70,
CURLINFO_LASTONE = 70
} CURLINFO;
/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
@@ -3230,6 +3232,50 @@ CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask);
#define CURLPAUSE_ALL (CURLPAUSE_RECV|CURLPAUSE_SEND)
#define CURLPAUSE_CONT (CURLPAUSE_RECV_CONT|CURLPAUSE_SEND_CONT)
/*
* NAME curl_easy_ssls_import()
*
* DESCRIPTION
*
* The curl_easy_ssls_import function adds a previously exported SSL session
* to the SSL session cache of the easy handle (or the underlying share).
*/
CURL_EXTERN CURLcode curl_easy_ssls_import(CURL *handle,
const char *session_key,
const unsigned char *shmac,
size_t shmac_len,
const unsigned char *sdata,
size_t sdata_len);
/* This is the curl_ssls_export_cb callback prototype. It
* is passed to curl_easy_ssls_export() to extract SSL sessions/tickets. */
typedef CURLcode curl_ssls_export_cb(CURL *handle,
void *userptr,
const char *session_key,
const unsigned char *shmac,
size_t shmac_len,
const unsigned char *sdata,
size_t sdata_len,
curl_off_t valid_until,
int ietf_tls_id,
const char *alpn,
size_t earlydata_max);
/*
* NAME curl_easy_ssls_export()
*
* DESCRIPTION
*
* The curl_easy_ssls_export function iterates over all SSL sessions stored
* in the easy handle (or underlying share) and invokes the passed
* callback.
*
*/
CURL_EXTERN CURLcode curl_easy_ssls_export(CURL *handle,
curl_ssls_export_cb *export_fn,
void *userptr);
#ifdef __cplusplus
} /* end of extern "C" */
#endif

View File

@@ -32,13 +32,13 @@
/* This is the version number of the libcurl package from which this header
file origins: */
#define LIBCURL_VERSION "8.11.1-DEV"
#define LIBCURL_VERSION "8.12.0-DEV"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 8
#define LIBCURL_VERSION_MINOR 11
#define LIBCURL_VERSION_PATCH 1
#define LIBCURL_VERSION_MINOR 12
#define LIBCURL_VERSION_PATCH 0
/* This is the numeric version of the libcurl version number, meant for easier
parsing and comparisons by programs. The LIBCURL_VERSION_NUM define will
@@ -59,7 +59,7 @@
CURL_VERSION_BITS() macro since curl's own configure script greps for it
and needs it to contain the full number.
*/
#define LIBCURL_VERSION_NUM 0x080b01
#define LIBCURL_VERSION_NUM 0x080c00
/*
* This is the date and time when the full source package was created. The

View File

@@ -78,7 +78,7 @@ CURL_EXTERN CURL *curl_easy_duphandle(CURL *curl);
*
* DESCRIPTION
*
* Re-initializes a CURL handle to the default values. This puts back the
* Re-initializes a curl handle to the default values. This puts back the
* handle to the same state as it was in when it was just created.
*
* It does keep: live connections, the Session ID cache, the DNS cache and the

View File

@@ -52,62 +52,24 @@
*
*/
#if defined(__DJGPP__) || defined(__GO32__)
# if defined(__DJGPP__) && (__DJGPP__ > 1)
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# else
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#elif defined(__SALFORDC__)
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
#if defined(__DJGPP__)
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#elif defined(__BORLANDC__)
# if (__BORLANDC__ < 0x520)
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# else
# define CURL_TYPEOF_CURL_OFF_T __int64
# define CURL_FORMAT_CURL_OFF_T "I64d"
# define CURL_FORMAT_CURL_OFF_TU "I64u"
# define CURL_SUFFIX_CURL_OFF_T i64
# define CURL_SUFFIX_CURL_OFF_TU ui64
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#elif defined(__TURBOC__)
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# define CURL_TYPEOF_CURL_OFF_T __int64
# define CURL_FORMAT_CURL_OFF_T "I64d"
# define CURL_FORMAT_CURL_OFF_TU "I64u"
# define CURL_SUFFIX_CURL_OFF_T i64
# define CURL_SUFFIX_CURL_OFF_TU ui64
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#elif defined(__POCC__)
# if (__POCC__ < 280)
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# elif defined(_MSC_VER)
# if defined(_MSC_VER)
# define CURL_TYPEOF_CURL_OFF_T __int64
# define CURL_FORMAT_CURL_OFF_T "I64d"
# define CURL_FORMAT_CURL_OFF_TU "I64u"
@@ -159,15 +121,21 @@
# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
#elif defined(__TANDEM)
# if ! defined(__LP64)
/* Required for 32-bit NonStop builds only. */
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# define CURL_TYPEOF_CURL_SOCKLEN_T int
# endif
# if !defined(__LP64)
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# define CURL_TYPEOF_CURL_SOCKLEN_T int
# else
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
# endif
#elif defined(_WIN32_WCE)
# define CURL_TYPEOF_CURL_OFF_T __int64
@@ -220,13 +188,7 @@
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# elif defined(_LP64)
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# else
# else /* _LP64 and default */
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
@@ -239,22 +201,13 @@
#elif defined(__370__)
# if defined(__IBMC__) || defined(__IBMCPP__)
# if defined(_ILP32)
# elif defined(_LP64)
# endif
# if defined(_LONG_LONG)
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# elif defined(_LP64)
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# else
# else /* _LP64 and default */
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
@@ -349,24 +302,15 @@
#elif defined(_MSC_VER)
# if (_MSC_VER >= 1800)
# include <inttypes.h>
# define CURL_TYPEOF_CURL_OFF_T __int64
# define CURL_FORMAT_CURL_OFF_T PRId64
# define CURL_FORMAT_CURL_OFF_TU PRIu64
# define CURL_SUFFIX_CURL_OFF_T i64
# define CURL_SUFFIX_CURL_OFF_TU ui64
# elif (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
# define CURL_TYPEOF_CURL_OFF_T __int64
# else
# define CURL_FORMAT_CURL_OFF_T "I64d"
# define CURL_FORMAT_CURL_OFF_TU "I64u"
# define CURL_SUFFIX_CURL_OFF_T i64
# define CURL_SUFFIX_CURL_OFF_TU ui64
# else
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# endif
# define CURL_TYPEOF_CURL_OFF_T __int64
# define CURL_SUFFIX_CURL_OFF_T i64
# define CURL_SUFFIX_CURL_OFF_TU ui64
# define CURL_TYPEOF_CURL_SOCKLEN_T int
/* ===================================== */
@@ -403,12 +347,12 @@
#else
/* generic "safe guess" on old 32-bit style */
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# define CURL_TYPEOF_CURL_SOCKLEN_T int
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#endif
#ifdef _AIX
@@ -462,7 +406,7 @@
#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \
defined(__HP_aCC) || defined(__BORLANDC__) || defined(__LCC__) || \
defined(__POCC__) || defined(__SALFORDC__) || defined(__HIGHC__) || \
defined(__POCC__) || defined(__HIGHC__) || \
defined(__ILEC400__)
/* This compiler is believed to have an ISO compatible preprocessor */
#define CURL_ISOCPP

View File

@@ -28,7 +28,7 @@ add_definitions("-DBUILDING_LIBCURL")
configure_file("curl_config.h.cmake" "${CMAKE_CURRENT_BINARY_DIR}/curl_config.h")
# Get 'CSOURCES', 'HHEADERS' variables
transform_makefile_inc("Makefile.inc" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake")
curl_transform_makefile_inc("Makefile.inc" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake")
include("${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake")
# DllMain is added later for DLL builds only.
@@ -105,9 +105,7 @@ if(SHARE_LIB_OBJECT)
set_property(TARGET ${LIB_OBJECT} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS")
endif()
if(CURL_HAS_LTO)
set_target_properties(${LIB_OBJECT} PROPERTIES
INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE
INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE)
set_target_properties(${LIB_OBJECT} PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()
target_include_directories(${LIB_OBJECT} INTERFACE
@@ -138,9 +136,7 @@ if(BUILD_STATIC_LIBS)
set_property(TARGET ${LIB_STATIC} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS")
endif()
if(CURL_HAS_LTO)
set_target_properties(${LIB_STATIC} PROPERTIES
INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE
INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE)
set_target_properties(${LIB_STATIC} PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()
target_include_directories(${LIB_STATIC} INTERFACE
@@ -177,9 +173,7 @@ if(BUILD_SHARED_LIBS)
set_property(TARGET ${LIB_SHARED} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS")
endif()
if(CURL_HAS_LTO)
set_target_properties(${LIB_SHARED} PROPERTIES
INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE
INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE)
set_target_properties(${LIB_SHARED} PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()
target_include_directories(${LIB_SHARED} INTERFACE
@@ -208,7 +202,7 @@ if(BUILD_SHARED_LIBS)
if(CURL_LIBCURL_SOVERSION OR CURL_LIBCURL_VERSIONED_SYMBOLS)
# Get 'VERSIONCHANGE', 'VERSIONADD', 'VERSIONDEL', 'VERSIONINFO' variables
transform_makefile_inc("Makefile.soname" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake")
curl_transform_makefile_inc("Makefile.soname" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake")
include("${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake")
math(EXPR _cmakesoname "${VERSIONCHANGE} - ${VERSIONDEL}")

View File

@@ -56,6 +56,8 @@ LIB_VTLS_CFILES = \
vtls/schannel_verify.c \
vtls/sectransp.c \
vtls/vtls.c \
vtls/vtls_scache.c \
vtls/vtls_spack.c \
vtls/wolfssl.c \
vtls/x509asn1.c
@@ -74,6 +76,8 @@ LIB_VTLS_HFILES = \
vtls/sectransp.h \
vtls/vtls.h \
vtls/vtls_int.h \
vtls/vtls_scache.h \
vtls/vtls_spack.h \
vtls/wolfssl.h \
vtls/x509asn1.h
@@ -112,7 +116,6 @@ LIB_CFILES = \
base64.c \
bufq.c \
bufref.c \
c-hyper.c \
cf-h1-proxy.c \
cf-h2-proxy.c \
cf-haproxy.c \
@@ -177,6 +180,7 @@ LIB_CFILES = \
http_negotiate.c \
http_ntlm.c \
http_proxy.c \
httpsrr.c \
idn.c \
if2ip.c \
imap.c \
@@ -223,6 +227,7 @@ LIB_CFILES = \
strcase.c \
strdup.c \
strerror.c \
strparse.c \
strtok.c \
strtoofft.c \
system_win32.c \
@@ -245,7 +250,6 @@ LIB_HFILES = \
asyn.h \
bufq.h \
bufref.h \
c-hyper.h \
cf-h1-proxy.h \
cf-h2-proxy.h \
cf-haproxy.h \
@@ -317,6 +321,7 @@ LIB_HFILES = \
http_negotiate.h \
http_ntlm.h \
http_proxy.h \
httpsrr.h \
idn.h \
if2ip.h \
imap.h \
@@ -344,7 +349,9 @@ LIB_HFILES = \
select.h \
sendf.h \
setopt.h \
setup-os400.h \
setup-vms.h \
setup-win32.h \
share.h \
sigpipe.h \
slist.h \
@@ -358,6 +365,7 @@ LIB_HFILES = \
strcase.h \
strdup.h \
strerror.h \
strparse.h \
strtok.h \
strtoofft.h \
system_win32.h \

View File

@@ -40,6 +40,8 @@
#include "rename.h"
#include "strdup.h"
#include "inet_pton.h"
#include "strparse.h"
#include "connect.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -47,28 +49,12 @@
#include "memdebug.h"
#define MAX_ALTSVC_LINE 4095
#define MAX_ALTSVC_DATELENSTR "64"
#define MAX_ALTSVC_DATELEN 64
#define MAX_ALTSVC_HOSTLENSTR "512"
#define MAX_ALTSVC_HOSTLEN 512
#define MAX_ALTSVC_ALPNLENSTR "10"
#define MAX_ALTSVC_DATELEN 256
#define MAX_ALTSVC_HOSTLEN 2048
#define MAX_ALTSVC_ALPNLEN 10
#define H3VERSION "h3"
static enum alpnid alpn2alpnid(char *name)
{
if(strcasecompare(name, "h1"))
return ALPN_h1;
if(strcasecompare(name, "h2"))
return ALPN_h2;
if(strcasecompare(name, H3VERSION))
return ALPN_h3;
if(strcasecompare(name, "http/1.1"))
return ALPN_h1;
return ALPN_none; /* unknown, probably rubbish input */
}
/* Given the ALPN ID, return the name */
const char *Curl_alpnid2str(enum alpnid id)
{
@@ -93,33 +79,33 @@ static void altsvc_free(struct altsvc *as)
}
static struct altsvc *altsvc_createid(const char *srchost,
size_t hlen,
const char *dsthost,
size_t dlen, /* dsthost length */
enum alpnid srcalpnid,
enum alpnid dstalpnid,
unsigned int srcport,
unsigned int dstport)
size_t srcport,
size_t dstport)
{
struct altsvc *as = calloc(1, sizeof(struct altsvc));
size_t hlen;
if(!as)
return NULL;
hlen = strlen(srchost);
DEBUGASSERT(hlen);
DEBUGASSERT(dlen);
if(!hlen || !dlen) {
if(!hlen || !dlen)
/* bad input */
free(as);
return NULL;
}
goto error;
if((hlen > 2) && srchost[0] == '[') {
/* IPv6 address, strip off brackets */
srchost++;
hlen -= 2;
}
else if(srchost[hlen - 1] == '.')
else if(srchost[hlen - 1] == '.') {
/* strip off trailing dot */
hlen--;
if(!hlen)
goto error;
}
if((dlen > 2) && dsthost[0] == '[') {
/* IPv6 address, strip off brackets */
dsthost++;
@@ -136,8 +122,8 @@ static struct altsvc *altsvc_createid(const char *srchost,
as->src.alpnid = srcalpnid;
as->dst.alpnid = dstalpnid;
as->src.port = curlx_ultous(srcport);
as->dst.port = curlx_ultous(dstport);
as->src.port = (unsigned short)srcport;
as->dst.port = (unsigned short)dstport;
return as;
error:
@@ -145,18 +131,19 @@ error:
return NULL;
}
static struct altsvc *altsvc_create(char *srchost,
char *dsthost,
char *srcalpn,
char *dstalpn,
unsigned int srcport,
unsigned int dstport)
static struct altsvc *altsvc_create(struct Curl_str *srchost,
struct Curl_str *dsthost,
struct Curl_str *srcalpn,
struct Curl_str *dstalpn,
size_t srcport,
size_t dstport)
{
enum alpnid dstalpnid = alpn2alpnid(dstalpn);
enum alpnid srcalpnid = alpn2alpnid(srcalpn);
enum alpnid dstalpnid = Curl_alpn2alpnid(dstalpn->str, dstalpn->len);
enum alpnid srcalpnid = Curl_alpn2alpnid(srcalpn->str, srcalpn->len);
if(!srcalpnid || !dstalpnid)
return NULL;
return altsvc_createid(srchost, dsthost, strlen(dsthost),
return altsvc_createid(srchost->str, srchost->len,
dsthost->str, dsthost->len,
srcalpnid, dstalpnid,
srcport, dstport);
}
@@ -167,31 +154,50 @@ static CURLcode altsvc_add(struct altsvcinfo *asi, char *line)
/* Example line:
h2 example.com 443 h3 shiny.example.com 8443 "20191231 10:00:00" 1
*/
char srchost[MAX_ALTSVC_HOSTLEN + 1];
char dsthost[MAX_ALTSVC_HOSTLEN + 1];
char srcalpn[MAX_ALTSVC_ALPNLEN + 1];
char dstalpn[MAX_ALTSVC_ALPNLEN + 1];
char date[MAX_ALTSVC_DATELEN + 1];
unsigned int srcport;
unsigned int dstport;
unsigned int prio;
unsigned int persist;
int rc;
struct Curl_str srchost;
struct Curl_str dsthost;
struct Curl_str srcalpn;
struct Curl_str dstalpn;
struct Curl_str date;
size_t srcport;
size_t dstport;
size_t persist;
size_t prio;
rc = sscanf(line,
"%" MAX_ALTSVC_ALPNLENSTR "s %" MAX_ALTSVC_HOSTLENSTR "s %u "
"%" MAX_ALTSVC_ALPNLENSTR "s %" MAX_ALTSVC_HOSTLENSTR "s %u "
"\"%" MAX_ALTSVC_DATELENSTR "[^\"]\" %u %u",
srcalpn, srchost, &srcport,
dstalpn, dsthost, &dstport,
date, &persist, &prio);
if(9 == rc) {
if(Curl_str_word(&line, &srcalpn, MAX_ALTSVC_ALPNLEN) ||
Curl_str_singlespace(&line) ||
Curl_str_word(&line, &srchost, MAX_ALTSVC_HOSTLEN) ||
Curl_str_singlespace(&line) ||
Curl_str_number(&line, &srcport, 65535) ||
Curl_str_singlespace(&line) ||
Curl_str_word(&line, &dstalpn, MAX_ALTSVC_ALPNLEN) ||
Curl_str_singlespace(&line) ||
Curl_str_word(&line, &dsthost, MAX_ALTSVC_HOSTLEN) ||
Curl_str_singlespace(&line) ||
Curl_str_number(&line, &dstport, 65535) ||
Curl_str_singlespace(&line) ||
Curl_str_quotedword(&line, &date, MAX_ALTSVC_DATELEN) ||
Curl_str_singlespace(&line) ||
Curl_str_number(&line, &persist, 1) ||
Curl_str_singlespace(&line) ||
Curl_str_number(&line, &prio, 0) ||
Curl_str_newline(&line))
;
else {
struct altsvc *as;
time_t expires = Curl_getdate_capped(date);
as = altsvc_create(srchost, dsthost, srcalpn, dstalpn, srcport, dstport);
char dbuf[MAX_ALTSVC_DATELEN + 1];
time_t expires;
/* The date parser works on a null terminated string. The maximum length
is upheld by Curl_str_quotedword(). */
memcpy(dbuf, date.str, date.len);
dbuf[date.len] = 0;
expires = Curl_getdate_capped(dbuf);
as = altsvc_create(&srchost, &dsthost, &srcalpn, &dstalpn, srcport,
dstport);
if(as) {
as->expires = expires;
as->prio = prio;
as->prio = 0; /* not supported to just set zero */
as->persist = persist ? 1 : 0;
Curl_llist_append(&asi->list, as, &as->node);
}
@@ -471,8 +477,6 @@ static time_t altsvc_debugtime(void *unused)
#define time(x) altsvc_debugtime(x)
#endif
#define ISNEWLINE(x) (((x) == '\n') || (x) == '\r')
/*
* Curl_altsvc_parse() takes an incoming alt-svc response header and stores
* the data correctly in the cache.
@@ -495,6 +499,8 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
unsigned short dstport = srcport; /* the same by default */
CURLcode result = getalnum(&p, alpnbuf, sizeof(alpnbuf));
size_t entries = 0;
size_t alpnlen = strlen(alpnbuf);
size_t srchostlen = strlen(srchost);
#ifdef CURL_DISABLE_VERBOSE_STRINGS
(void)data;
#endif
@@ -515,7 +521,7 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
do {
if(*p == '=') {
/* [protocol]="[host][:port]" */
enum alpnid dstalpnid = alpn2alpnid(alpnbuf); /* the same by default */
enum alpnid dstalpnid = Curl_alpn2alpnid(alpnbuf, alpnlen);
p++;
if(*p == '\"') {
const char *dsthost = "";
@@ -633,13 +639,18 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
this is the first entry of the line. */
altsvc_flush(asi, srcalpnid, srchost, srcport);
as = altsvc_createid(srchost, dsthost, dstlen,
as = altsvc_createid(srchost, srchostlen,
dsthost, dstlen,
srcalpnid, dstalpnid,
srcport, dstport);
if(as) {
/* The expires time also needs to take the Age: value (if any) into
account. [See RFC 7838 section 3.1] */
as->expires = maxage + time(NULL);
time_t secs = time(NULL);
/* The expires time also needs to take the Age: value (if any)
into account. [See RFC 7838 section 3.1] */
if(maxage > (TIME_T_MAX - secs))
as->expires = TIME_T_MAX;
else
as->expires = maxage + secs;
as->persist = persist;
Curl_llist_append(&asi->list, as, &as->node);
infof(data, "Added alt-svc: %s:%d over %s", dsthost, dstport,

View File

@@ -29,13 +29,6 @@
#include <curl/curl.h>
#include "llist.h"
enum alpnid {
ALPN_none = 0,
ALPN_h1 = CURLALTSVC_H1,
ALPN_h2 = CURLALTSVC_H2,
ALPN_h3 = CURLALTSVC_H3
};
struct althost {
char *host;
unsigned short port;

View File

@@ -196,12 +196,11 @@ int Curl_amiga_select(int nfds, fd_set *readfds, fd_set *writefds,
*/
struct Library *SocketBase = NULL;
extern int errno, h_errno;
#ifdef __libnix__
void __request(const char *msg);
#else
# define __request(msg) Printf(msg "\n\a")
# define __request(msg) Printf((const unsigned char *)(msg "\n\a"), 0)
#endif
void Curl_amiga_cleanup(void)
@@ -215,7 +214,7 @@ void Curl_amiga_cleanup(void)
CURLcode Curl_amiga_init(void)
{
if(!SocketBase)
SocketBase = OpenLibrary("bsdsocket.library", 4);
SocketBase = OpenLibrary((const unsigned char *)"bsdsocket.library", 4);
if(!SocketBase) {
__request("No TCP/IP Stack running!");

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>
@@ -59,15 +59,101 @@
#include "select.h"
#include "progress.h"
#include "timediff.h"
#include "httpsrr.h"
#include "strdup.h"
#if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
defined(_WIN32)
# define CARES_STATICLIB
#endif
#include <ares.h>
#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
@@ -93,22 +179,19 @@
#define HAVE_CARES_GETADDRINFO 1
#endif
#if ARES_VERSION >= 0x011c00
/* 1.28.0 and later have ares_query_dnsrec */
#define HAVE_ARES_QUERY_DNSREC 1
#ifdef USE_HTTPSRR
#define USE_HTTPSRR_ARES 1
#endif
#endif
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#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
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.
@@ -280,89 +363,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);
}
/*
@@ -381,7 +388,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
@@ -417,8 +424,19 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
if(!data->state.async.dns)
result = Curl_resolver_error(data);
else
else {
*dns = data->state.async.dns;
#ifdef USE_HTTPSRR_ARES
{
struct Curl_https_rrinfo *lhrr =
Curl_memdup(&res->hinfo, sizeof(struct Curl_https_rrinfo));
if(!lhrr)
result = CURLE_OUT_OF_MEMORY;
else
(*dns)->hinfo = lhrr;
}
#endif
}
destroy_async_data(&data->state.async);
}
@@ -481,7 +499,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);
@@ -745,6 +764,7 @@ static void addrinfo_cb(void *arg, int status, int timeouts,
}
#endif
/*
* Curl_resolver_getaddrinfo() - when using ares
*
@@ -826,6 +846,16 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
hostname, PF_INET,
query_completed_cb, data);
}
#endif
#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,
Curl_dnsrec_done_cb, data, NULL);
}
#endif
*waitp = 1; /* expect asynchronous response */
}
@@ -838,14 +868,26 @@ CURLcode Curl_set_dns_servers(struct Curl_easy *data,
CURLcode result = CURLE_NOT_BUILT_IN;
int ares_result;
/* If server is NULL or empty, this would purge all DNS servers
* from ares library, which will cause any and all queries to fail.
* So, just return OK if none are configured and do not actually make
* any changes to c-ares. This lets c-ares use its defaults, which
* it gets from the OS (for instance from /etc/resolv.conf on Linux).
/* If server is NULL, this purges all DNS servers from c-ares. Reset it to
* default.
*/
if(!(servers && servers[0]))
return CURLE_OK;
if(!servers) {
Curl_resolver_cleanup(data->state.async.resolver);
result = Curl_resolver_init(data, &data->state.async.resolver);
if(!result) {
/* this now needs to restore the other options set to c-ares */
if(data->set.str[STRING_DNS_INTERFACE])
(void)Curl_set_dns_interface(data,
data->set.str[STRING_DNS_INTERFACE]);
if(data->set.str[STRING_DNS_LOCAL_IP4])
(void)Curl_set_dns_local_ip4(data,
data->set.str[STRING_DNS_LOCAL_IP4]);
if(data->set.str[STRING_DNS_LOCAL_IP6])
(void)Curl_set_dns_local_ip6(data,
data->set.str[STRING_DNS_LOCAL_IP6]);
}
return result;
}
#ifdef HAVE_CARES_SERVERS_CSV
#ifdef HAVE_CARES_PORTS_CSV
@@ -947,3 +989,5 @@ CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data,
#endif
}
#endif /* CURLRES_ARES */
#endif /* USE_ARES */

View File

@@ -64,6 +64,15 @@
#include "inet_ntop.h"
#include "curl_threads.h"
#include "connect.h"
#include "strdup.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 +154,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);
@@ -195,9 +178,11 @@ void destroy_thread_sync_data(struct thread_sync_data *tsd)
* close one end of the socket pair (may be done in resolver thread);
* the other end (for reading) is always closed in the parent thread.
*/
#ifndef USE_EVENTFD
if(tsd->sock_pair[1] != CURL_SOCKET_BAD) {
wakeup_close(tsd->sock_pair[1]);
}
#endif
#endif
memset(tsd, 0, sizeof(*tsd));
}
@@ -218,7 +203,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;
@@ -341,7 +326,7 @@ CURL_STDCALL getaddrinfo_thread(void *arg)
}
}
#endif
tsd->done = 1;
tsd->done = TRUE;
Curl_mutex_release(tsd->mtx);
}
@@ -380,7 +365,7 @@ CURL_STDCALL gethostbyname_thread(void *arg)
free(td);
}
else {
tsd->done = 1;
tsd->done = TRUE;
Curl_mutex_release(tsd->mtx);
}
@@ -396,19 +381,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) {
@@ -437,6 +425,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_options(&asp->tdata->channel, NULL, 0);
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.
@@ -472,8 +478,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);
@@ -483,11 +489,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:
@@ -585,7 +594,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;
@@ -594,6 +603,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;
@@ -607,6 +620,17 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
destroy_async_data(&data->state.async);
return result;
}
#ifdef USE_HTTPSRR_ARES
{
struct Curl_https_rrinfo *lhrr =
Curl_memdup(&td->hinfo, sizeof(struct Curl_https_rrinfo));
if(!lhrr) {
destroy_async_data(&data->state.async);
return CURLE_OUT_OF_MEMORY;
}
data->state.async.dns->hinfo = lhrr;
}
#endif
destroy_async_data(&data->state.async);
*entry = data->state.async.dns;
}
@@ -641,18 +665,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

@@ -45,11 +45,6 @@ static size_t chunk_len(const struct buf_chunk *chunk)
return chunk->w_offset - chunk->r_offset;
}
static size_t chunk_space(const struct buf_chunk *chunk)
{
return chunk->dlen - chunk->w_offset;
}
static void chunk_reset(struct buf_chunk *chunk)
{
chunk->next = NULL;
@@ -287,24 +282,6 @@ size_t Curl_bufq_len(const struct bufq *q)
return len;
}
size_t Curl_bufq_space(const struct bufq *q)
{
size_t space = 0;
if(q->tail)
space += chunk_space(q->tail);
if(q->spare) {
struct buf_chunk *chunk = q->spare;
while(chunk) {
space += chunk->dlen;
chunk = chunk->next;
}
}
if(q->chunk_count < q->max_chunks) {
space += (q->max_chunks - q->chunk_count) * q->chunk_size;
}
return space;
}
bool Curl_bufq_is_empty(const struct bufq *q)
{
return !q->head || chunk_is_empty(q->head);

View File

@@ -150,14 +150,6 @@ void Curl_bufq_free(struct bufq *q);
*/
size_t Curl_bufq_len(const struct bufq *q);
/**
* Return the total amount of free space in the queue.
* The returned length is the number of bytes that can
* be expected to be written successfully to the bufq,
* providing no memory allocations fail.
*/
size_t Curl_bufq_space(const struct bufq *q);
/**
* Returns TRUE iff there is no data in the buffer queue.
*/

File diff suppressed because it is too large Load Diff

View File

@@ -1,63 +0,0 @@
#ifndef HEADER_CURL_HYPER_H
#define HEADER_CURL_HYPER_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 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
* are also available at https://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#if !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER)
#include <hyper.h>
struct hyp_io_ctx {
struct Curl_easy *data;
int sockindex;
};
/* per-transfer data for the Hyper backend */
struct hyptransfer {
hyper_waker *write_waker;
hyper_waker *read_waker;
const hyper_executor *exec;
hyper_waker *send_body_waker;
struct hyp_io_ctx io_ctx;
};
size_t Curl_hyper_recv(void *userp, hyper_context *ctx,
uint8_t *buf, size_t buflen);
size_t Curl_hyper_send(void *userp, hyper_context *ctx,
const uint8_t *buf, size_t buflen);
CURLcode Curl_hyper_stream(struct Curl_easy *data,
struct connectdata *conn,
int *didwhat,
int select_res);
CURLcode Curl_hyper_header(struct Curl_easy *data, hyper_headers *headers,
const char *line);
void Curl_hyper_done(struct Curl_easy *);
#else
#define Curl_hyper_done(x)
#endif /* !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER) */
#endif /* HEADER_CURL_HYPER_H */

View File

@@ -27,9 +27,6 @@
#if !defined(CURL_DISABLE_PROXY) && !defined(CURL_DISABLE_HTTP)
#include <curl/curl.h>
#ifdef USE_HYPER
#include <hyper.h>
#endif
#include "urldata.h"
#include "dynbuf.h"
#include "sendf.h"
@@ -184,9 +181,6 @@ static void h1_tunnel_go_state(struct Curl_cfilter *cf,
make sure that it is not accidentally used for the document request
after we have connected. So let's free and clear it here. */
Curl_safefree(data->state.aptr.proxyuserpwd);
#ifdef USE_HYPER
data->state.hconnect = FALSE;
#endif
break;
}
}
@@ -209,10 +203,9 @@ static void tunnel_free(struct Curl_cfilter *cf,
static bool tunnel_want_send(struct h1_tunnel_state *ts)
{
return (ts->tunnel_state == H1_TUNNEL_CONNECT);
return ts->tunnel_state == H1_TUNNEL_CONNECT;
}
#ifndef USE_HYPER
static CURLcode start_CONNECT(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct h1_tunnel_state *ts)
@@ -529,337 +522,6 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
return result;
}
#else /* USE_HYPER */
static CURLcode CONNECT_host(struct Curl_cfilter *cf,
struct Curl_easy *data,
char **pauthority,
char **phost_header)
{
const char *hostname;
int port;
bool ipv6_ip;
CURLcode result;
char *authority; /* for CONNECT, the destination host + port */
char *host_header = NULL; /* Host: authority */
result = Curl_http_proxy_get_destination(cf, &hostname, &port, &ipv6_ip);
if(result)
return result;
authority = aprintf("%s%s%s:%d", ipv6_ip ? "[":"", hostname,
ipv6_ip ? "]" : "", port);
if(!authority)
return CURLE_OUT_OF_MEMORY;
/* If user is not overriding the Host header later */
if(!Curl_checkProxyheaders(data, cf->conn, STRCONST("Host"))) {
host_header = aprintf("Host: %s\r\n", authority);
if(!host_header) {
free(authority);
return CURLE_OUT_OF_MEMORY;
}
}
*pauthority = authority;
*phost_header = host_header;
return CURLE_OK;
}
/* The Hyper version of CONNECT */
static CURLcode start_CONNECT(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct h1_tunnel_state *ts)
{
struct connectdata *conn = cf->conn;
struct hyptransfer *h = &data->hyp;
curl_socket_t tunnelsocket = Curl_conn_cf_get_socket(cf, data);
hyper_io *io = NULL;
hyper_request *req = NULL;
hyper_headers *headers = NULL;
hyper_clientconn_options *options = NULL;
hyper_task *handshake = NULL;
hyper_task *task = NULL; /* for the handshake */
hyper_clientconn *client = NULL;
hyper_task *sendtask = NULL; /* for the send */
char *authority = NULL; /* for CONNECT */
char *host_header = NULL; /* Host: */
CURLcode result = CURLE_OUT_OF_MEMORY;
(void)ts;
io = hyper_io_new();
if(!io) {
failf(data, "Couldn't create hyper IO");
result = CURLE_OUT_OF_MEMORY;
goto error;
}
/* tell Hyper how to read/write network data */
h->io_ctx.data = data;
h->io_ctx.sockindex = cf->sockindex;
hyper_io_set_userdata(io, &h->io_ctx);
hyper_io_set_read(io, Curl_hyper_recv);
hyper_io_set_write(io, Curl_hyper_send);
conn->sockfd = tunnelsocket;
data->state.hconnect = TRUE;
/* create an executor to poll futures */
if(!h->exec) {
h->exec = hyper_executor_new();
if(!h->exec) {
failf(data, "Couldn't create hyper executor");
result = CURLE_OUT_OF_MEMORY;
goto error;
}
}
options = hyper_clientconn_options_new();
if(!options) {
failf(data, "Couldn't create hyper client options");
result = CURLE_OUT_OF_MEMORY;
goto error;
}
hyper_clientconn_options_set_preserve_header_case(options, 1);
hyper_clientconn_options_set_preserve_header_order(options, 1);
hyper_clientconn_options_exec(options, h->exec);
/* "Both the `io` and the `options` are consumed in this function
call" */
handshake = hyper_clientconn_handshake(io, options);
if(!handshake) {
failf(data, "Couldn't create hyper client handshake");
result = CURLE_OUT_OF_MEMORY;
goto error;
}
io = NULL;
options = NULL;
if(HYPERE_OK != hyper_executor_push(h->exec, handshake)) {
failf(data, "Couldn't hyper_executor_push the handshake");
result = CURLE_OUT_OF_MEMORY;
goto error;
}
handshake = NULL; /* ownership passed on */
task = hyper_executor_poll(h->exec);
if(!task) {
failf(data, "Couldn't hyper_executor_poll the handshake");
result = CURLE_OUT_OF_MEMORY;
goto error;
}
client = hyper_task_value(task);
hyper_task_free(task);
req = hyper_request_new();
if(!req) {
failf(data, "Couldn't hyper_request_new");
result = CURLE_OUT_OF_MEMORY;
goto error;
}
if(hyper_request_set_method(req, (uint8_t *)"CONNECT",
strlen("CONNECT"))) {
failf(data, "error setting method");
result = CURLE_OUT_OF_MEMORY;
goto error;
}
/* This only happens if we have looped here due to authentication
reasons, and we do not really use the newly cloned URL here
then. Just free() it. */
Curl_safefree(data->req.newurl);
result = CONNECT_host(cf, data, &authority, &host_header);
if(result)
goto error;
infof(data, "Establish HTTP proxy tunnel to %s", authority);
if(hyper_request_set_uri(req, (uint8_t *)authority,
strlen(authority))) {
failf(data, "error setting path");
result = CURLE_OUT_OF_MEMORY;
goto error;
}
if(data->set.verbose) {
char *se = aprintf("CONNECT %s HTTP/1.1\r\n", authority);
if(!se) {
result = CURLE_OUT_OF_MEMORY;
goto error;
}
Curl_debug(data, CURLINFO_HEADER_OUT, se, strlen(se));
free(se);
}
/* Setup the proxy-authorization header, if any */
result = Curl_http_output_auth(data, conn, "CONNECT", HTTPREQ_GET,
authority, TRUE);
if(result)
goto error;
Curl_safefree(authority);
/* default is 1.1 */
if((conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) &&
(HYPERE_OK != hyper_request_set_version(req,
HYPER_HTTP_VERSION_1_0))) {
failf(data, "error setting HTTP version");
result = CURLE_OUT_OF_MEMORY;
goto error;
}
headers = hyper_request_headers(req);
if(!headers) {
failf(data, "hyper_request_headers");
result = CURLE_OUT_OF_MEMORY;
goto error;
}
if(host_header) {
result = Curl_hyper_header(data, headers, host_header);
if(result)
goto error;
Curl_safefree(host_header);
}
if(data->state.aptr.proxyuserpwd) {
result = Curl_hyper_header(data, headers,
data->state.aptr.proxyuserpwd);
if(result)
goto error;
}
if(!Curl_checkProxyheaders(data, conn, STRCONST("User-Agent")) &&
data->set.str[STRING_USERAGENT] && *data->set.str[STRING_USERAGENT]) {
struct dynbuf ua;
Curl_dyn_init(&ua, DYN_HTTP_REQUEST);
result = Curl_dyn_addf(&ua, "User-Agent: %s\r\n",
data->set.str[STRING_USERAGENT]);
if(result)
goto error;
result = Curl_hyper_header(data, headers, Curl_dyn_ptr(&ua));
if(result)
goto error;
Curl_dyn_free(&ua);
}
if(!Curl_checkProxyheaders(data, conn, STRCONST("Proxy-Connection"))) {
result = Curl_hyper_header(data, headers,
"Proxy-Connection: Keep-Alive");
if(result)
goto error;
}
result = Curl_add_custom_headers(data, TRUE, headers);
if(result)
goto error;
result = Curl_creader_set_null(data);
if(result)
goto error;
sendtask = hyper_clientconn_send(client, req);
if(!sendtask) {
failf(data, "hyper_clientconn_send");
result = CURLE_OUT_OF_MEMORY;
goto error;
}
req = NULL;
if(HYPERE_OK != hyper_executor_push(h->exec, sendtask)) {
failf(data, "Couldn't hyper_executor_push the send");
result = CURLE_OUT_OF_MEMORY;
goto error;
}
sendtask = NULL; /* ownership passed on */
hyper_clientconn_free(client);
client = NULL;
error:
free(host_header);
free(authority);
if(io)
hyper_io_free(io);
if(options)
hyper_clientconn_options_free(options);
if(handshake)
hyper_task_free(handshake);
if(client)
hyper_clientconn_free(client);
if(req)
hyper_request_free(req);
return result;
}
static CURLcode send_CONNECT(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct h1_tunnel_state *ts,
bool *done)
{
struct hyptransfer *h = &data->hyp;
struct connectdata *conn = cf->conn;
hyper_task *task = NULL;
hyper_error *hypererr = NULL;
CURLcode result = CURLE_OK;
(void)ts;
(void)conn;
do {
task = hyper_executor_poll(h->exec);
if(task) {
bool error = hyper_task_type(task) == HYPER_TASK_ERROR;
if(error)
hypererr = hyper_task_value(task);
hyper_task_free(task);
if(error) {
/* this could probably use a better error code? */
result = CURLE_OUT_OF_MEMORY;
goto error;
}
}
} while(task);
error:
*done = (result == CURLE_OK);
if(hypererr) {
uint8_t errbuf[256];
size_t errlen = hyper_error_print(hypererr, errbuf, sizeof(errbuf));
failf(data, "Hyper: %.*s", (int)errlen, errbuf);
hyper_error_free(hypererr);
}
return result;
}
static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct h1_tunnel_state *ts,
bool *done)
{
struct hyptransfer *h = &data->hyp;
CURLcode result;
int didwhat;
(void)ts;
result = Curl_hyper_stream(data, cf->conn, &didwhat,
CURL_CSELECT_IN | CURL_CSELECT_OUT);
*done = data->req.done;
if(result || !*done)
return result;
if(h->exec) {
hyper_executor_free(h->exec);
h->exec = NULL;
}
if(h->read_waker) {
hyper_waker_free(h->read_waker);
h->read_waker = NULL;
}
if(h->write_waker) {
hyper_waker_free(h->write_waker);
h->write_waker = NULL;
}
return result;
}
#endif /* USE_HYPER */
static CURLcode H1_CONNECT(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct h1_tunnel_state *ts)

View File

@@ -865,7 +865,9 @@ static int tunnel_recv_callback(nghttp2_session *session, uint8_t flags,
if(nwritten < 0) {
if(result != CURLE_AGAIN)
return NGHTTP2_ERR_CALLBACK_FAILURE;
#ifdef DEBUGBUILD
nwritten = 0;
#endif
}
DEBUGASSERT((size_t)nwritten == len);
return 0;

View File

@@ -24,13 +24,14 @@
#include "curl_setup.h"
#if !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER)
#if !defined(CURL_DISABLE_HTTP)
#include "urldata.h"
#include <curl/curl.h>
#include "curl_trc.h"
#include "cfilters.h"
#include "connect.h"
#include "hostip.h"
#include "multiif.h"
#include "cf-https-connect.h"
#include "http2.h"
@@ -42,6 +43,10 @@
#include "memdebug.h"
#ifndef ARRAYSIZE
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
#endif
typedef enum {
CF_HC_INIT,
CF_HC_CONNECT,
@@ -55,7 +60,7 @@ struct cf_hc_baller {
CURLcode result;
struct curltime started;
int reply_ms;
BIT(enabled);
enum alpnid alpn_id;
BIT(shutdown);
};
@@ -73,7 +78,7 @@ static void cf_hc_baller_reset(struct cf_hc_baller *b,
static bool cf_hc_baller_is_active(struct cf_hc_baller *b)
{
return b->enabled && b->cf && !b->result;
return b->cf && !b->result;
}
static bool cf_hc_baller_has_started(struct cf_hc_baller *b)
@@ -84,7 +89,7 @@ static bool cf_hc_baller_has_started(struct cf_hc_baller *b)
static int cf_hc_baller_reply_ms(struct cf_hc_baller *b,
struct Curl_easy *data)
{
if(b->reply_ms < 0)
if(b->cf && (b->reply_ms < 0))
b->cf->cft->query(b->cf, data, CF_QUERY_CONNECT_REPLY_MS,
&b->reply_ms, NULL);
return b->reply_ms;
@@ -116,26 +121,53 @@ struct cf_hc_ctx {
const struct Curl_dns_entry *remotehost;
struct curltime started; /* when connect started */
CURLcode result; /* overall result */
struct cf_hc_baller h3_baller;
struct cf_hc_baller h21_baller;
struct cf_hc_baller ballers[2];
size_t baller_count;
unsigned int soft_eyeballs_timeout_ms;
unsigned int hard_eyeballs_timeout_ms;
};
static void cf_hc_baller_assign(struct cf_hc_baller *b,
enum alpnid alpn_id)
{
b->alpn_id = alpn_id;
switch(b->alpn_id) {
case ALPN_h3:
b->name = "h3";
break;
case ALPN_h2:
b->name = "h2";
break;
case ALPN_h1:
b->name = "h1";
break;
default:
b->result = CURLE_FAILED_INIT;
break;
}
}
static void cf_hc_baller_init(struct cf_hc_baller *b,
struct Curl_cfilter *cf,
struct Curl_easy *data,
const char *name,
int transport)
{
struct cf_hc_ctx *ctx = cf->ctx;
struct Curl_cfilter *save = cf->next;
b->name = name;
cf->next = NULL;
b->started = Curl_now();
b->result = Curl_cf_setup_insert_after(cf, data, ctx->remotehost,
transport, CURL_CF_SSL_ENABLE);
switch(b->alpn_id) {
case ALPN_h3:
transport = TRNSPRT_QUIC;
break;
default:
break;
}
if(!b->result)
b->result = Curl_cf_setup_insert_after(cf, data, ctx->remotehost,
transport, CURL_CF_SSL_ENABLE);
b->cf = cf->next;
cf->next = save;
}
@@ -157,10 +189,11 @@ static CURLcode cf_hc_baller_connect(struct cf_hc_baller *b,
static void cf_hc_reset(struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct cf_hc_ctx *ctx = cf->ctx;
size_t i;
if(ctx) {
cf_hc_baller_reset(&ctx->h3_baller, data);
cf_hc_baller_reset(&ctx->h21_baller, data);
for(i = 0; i < ctx->baller_count; ++i)
cf_hc_baller_reset(&ctx->ballers[i], data);
ctx->state = CF_HC_INIT;
ctx->result = CURLE_OK;
ctx->hard_eyeballs_timeout_ms = data->set.happy_eyeballs_timeout;
@@ -175,12 +208,12 @@ static CURLcode baller_connected(struct Curl_cfilter *cf,
struct cf_hc_ctx *ctx = cf->ctx;
CURLcode result = CURLE_OK;
int reply_ms;
size_t i;
DEBUGASSERT(winner->cf);
if(winner != &ctx->h3_baller)
cf_hc_baller_reset(&ctx->h3_baller, data);
if(winner != &ctx->h21_baller)
cf_hc_baller_reset(&ctx->h21_baller, data);
for(i = 0; i < ctx->baller_count; ++i)
if(winner != &ctx->ballers[i])
cf_hc_baller_reset(&ctx->ballers[i], data);
reply_ms = cf_hc_baller_reply_ms(winner, data);
if(reply_ms >= 0)
@@ -218,31 +251,40 @@ static CURLcode baller_connected(struct Curl_cfilter *cf,
}
static bool time_to_start_h21(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct curltime now)
static bool time_to_start_next(struct Curl_cfilter *cf,
struct Curl_easy *data,
size_t idx, struct curltime now)
{
struct cf_hc_ctx *ctx = cf->ctx;
timediff_t elapsed_ms;
size_t i;
if(!ctx->h21_baller.enabled || cf_hc_baller_has_started(&ctx->h21_baller))
if(idx >= ctx->baller_count)
return FALSE;
if(!ctx->h3_baller.enabled || !cf_hc_baller_is_active(&ctx->h3_baller))
if(cf_hc_baller_has_started(&ctx->ballers[idx]))
return FALSE;
for(i = 0; i < idx; i++) {
if(!ctx->ballers[i].result)
break;
}
if(i == idx) {
CURL_TRC_CF(data, cf, "all previous ballers have failed, time to start "
"baller %zu [%s]", idx, ctx->ballers[idx].name);
return TRUE;
}
elapsed_ms = Curl_timediff(now, ctx->started);
if(elapsed_ms >= ctx->hard_eyeballs_timeout_ms) {
CURL_TRC_CF(data, cf, "hard timeout of %dms reached, starting h21",
ctx->hard_eyeballs_timeout_ms);
CURL_TRC_CF(data, cf, "hard timeout of %dms reached, starting %s",
ctx->hard_eyeballs_timeout_ms, ctx->ballers[idx].name);
return TRUE;
}
if(elapsed_ms >= ctx->soft_eyeballs_timeout_ms) {
if(cf_hc_baller_reply_ms(&ctx->h3_baller, data) < 0) {
CURL_TRC_CF(data, cf, "soft timeout of %dms reached, h3 has not "
"seen any data, starting h21",
ctx->soft_eyeballs_timeout_ms);
if((idx > 0) && (elapsed_ms >= ctx->soft_eyeballs_timeout_ms)) {
if(cf_hc_baller_reply_ms(&ctx->ballers[idx - 1], data) < 0) {
CURL_TRC_CF(data, cf, "soft timeout of %dms reached, %s has not "
"seen any data, starting %s",
ctx->soft_eyeballs_timeout_ms,
ctx->ballers[idx - 1].name, ctx->ballers[idx].name);
return TRUE;
}
/* set the effective hard timeout again */
@@ -259,6 +301,7 @@ static CURLcode cf_hc_connect(struct Curl_cfilter *cf,
struct cf_hc_ctx *ctx = cf->ctx;
struct curltime now;
CURLcode result = CURLE_OK;
size_t i, failed_ballers;
(void)blocking;
if(cf->connected) {
@@ -270,51 +313,57 @@ static CURLcode cf_hc_connect(struct Curl_cfilter *cf,
now = Curl_now();
switch(ctx->state) {
case CF_HC_INIT:
DEBUGASSERT(!ctx->h3_baller.cf);
DEBUGASSERT(!ctx->h21_baller.cf);
DEBUGASSERT(!cf->next);
for(i = 0; i < ctx->baller_count; i++)
DEBUGASSERT(!ctx->ballers[i].cf);
CURL_TRC_CF(data, cf, "connect, init");
ctx->started = now;
if(ctx->h3_baller.enabled) {
cf_hc_baller_init(&ctx->h3_baller, cf, data, "h3", TRNSPRT_QUIC);
if(ctx->h21_baller.enabled)
Curl_expire(data, ctx->soft_eyeballs_timeout_ms, EXPIRE_ALPN_EYEBALLS);
cf_hc_baller_init(&ctx->ballers[0], cf, data, cf->conn->transport);
if(ctx->baller_count > 1) {
Curl_expire(data, ctx->soft_eyeballs_timeout_ms, EXPIRE_ALPN_EYEBALLS);
CURL_TRC_CF(data, cf, "set expire for starting next baller in %ums",
ctx->soft_eyeballs_timeout_ms);
}
else if(ctx->h21_baller.enabled)
cf_hc_baller_init(&ctx->h21_baller, cf, data, "h21",
cf->conn->transport);
ctx->state = CF_HC_CONNECT;
FALLTHROUGH();
case CF_HC_CONNECT:
if(cf_hc_baller_is_active(&ctx->h3_baller)) {
result = cf_hc_baller_connect(&ctx->h3_baller, cf, data, done);
if(cf_hc_baller_is_active(&ctx->ballers[0])) {
result = cf_hc_baller_connect(&ctx->ballers[0], cf, data, done);
if(!result && *done) {
result = baller_connected(cf, data, &ctx->h3_baller);
result = baller_connected(cf, data, &ctx->ballers[0]);
goto out;
}
}
if(time_to_start_h21(cf, data, now)) {
cf_hc_baller_init(&ctx->h21_baller, cf, data, "h21",
cf->conn->transport);
if(time_to_start_next(cf, data, 1, now)) {
cf_hc_baller_init(&ctx->ballers[1], cf, data, cf->conn->transport);
}
if(cf_hc_baller_is_active(&ctx->h21_baller)) {
CURL_TRC_CF(data, cf, "connect, check h21");
result = cf_hc_baller_connect(&ctx->h21_baller, cf, data, done);
if((ctx->baller_count > 1) && cf_hc_baller_is_active(&ctx->ballers[1])) {
CURL_TRC_CF(data, cf, "connect, check %s", ctx->ballers[1].name);
result = cf_hc_baller_connect(&ctx->ballers[1], cf, data, done);
if(!result && *done) {
result = baller_connected(cf, data, &ctx->h21_baller);
result = baller_connected(cf, data, &ctx->ballers[1]);
goto out;
}
}
if((!ctx->h3_baller.enabled || ctx->h3_baller.result) &&
(!ctx->h21_baller.enabled || ctx->h21_baller.result)) {
/* both failed or disabled. we give up */
failed_ballers = 0;
for(i = 0; i < ctx->baller_count; i++) {
if(ctx->ballers[i].result)
++failed_ballers;
}
if(failed_ballers == ctx->baller_count) {
/* all have failed. we give up */
CURL_TRC_CF(data, cf, "connect, all failed");
result = ctx->result = ctx->h3_baller.enabled ?
ctx->h3_baller.result : ctx->h21_baller.result;
for(i = 0; i < ctx->baller_count; i++) {
if(ctx->ballers[i].result) {
result = ctx->ballers[i].result;
break;
}
}
ctx->state = CF_HC_FAILURE;
goto out;
}
@@ -344,7 +393,6 @@ static CURLcode cf_hc_shutdown(struct Curl_cfilter *cf,
struct Curl_easy *data, bool *done)
{
struct cf_hc_ctx *ctx = cf->ctx;
struct cf_hc_baller *ballers[2];
size_t i;
CURLcode result = CURLE_OK;
@@ -356,10 +404,8 @@ static CURLcode cf_hc_shutdown(struct Curl_cfilter *cf,
/* shutdown all ballers that have not done so already. If one fails,
* continue shutting down others until all are shutdown. */
ballers[0] = &ctx->h3_baller;
ballers[1] = &ctx->h21_baller;
for(i = 0; i < sizeof(ballers)/sizeof(ballers[0]); i++) {
struct cf_hc_baller *b = ballers[i];
for(i = 0; i < ctx->baller_count; i++) {
struct cf_hc_baller *b = &ctx->ballers[i];
bool bdone = FALSE;
if(!cf_hc_baller_is_active(b) || b->shutdown)
continue;
@@ -369,14 +415,14 @@ static CURLcode cf_hc_shutdown(struct Curl_cfilter *cf,
}
*done = TRUE;
for(i = 0; i < sizeof(ballers)/sizeof(ballers[0]); i++) {
if(ballers[i] && !ballers[i]->shutdown)
for(i = 0; i < ctx->baller_count; i++) {
if(!ctx->ballers[i].shutdown)
*done = FALSE;
}
if(*done) {
for(i = 0; i < sizeof(ballers)/sizeof(ballers[0]); i++) {
if(ballers[i] && ballers[i]->result)
result = ballers[i]->result;
for(i = 0; i < ctx->baller_count; i++) {
if(ctx->ballers[i].result)
result = ctx->ballers[i].result;
}
}
CURL_TRC_CF(data, cf, "shutdown -> %d, done=%d", result, *done);
@@ -389,13 +435,10 @@ static void cf_hc_adjust_pollset(struct Curl_cfilter *cf,
{
if(!cf->connected) {
struct cf_hc_ctx *ctx = cf->ctx;
struct cf_hc_baller *ballers[2];
size_t i;
ballers[0] = &ctx->h3_baller;
ballers[1] = &ctx->h21_baller;
for(i = 0; i < sizeof(ballers)/sizeof(ballers[0]); i++) {
struct cf_hc_baller *b = ballers[i];
for(i = 0; i < ctx->baller_count; i++) {
struct cf_hc_baller *b = &ctx->ballers[i];
if(!cf_hc_baller_is_active(b))
continue;
Curl_conn_cf_adjust_pollset(b->cf, data, ps);
@@ -408,13 +451,16 @@ static bool cf_hc_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data)
{
struct cf_hc_ctx *ctx = cf->ctx;
size_t i;
if(cf->connected)
return cf->next->cft->has_data_pending(cf->next, data);
CURL_TRC_CF((struct Curl_easy *)data, cf, "data_pending");
return cf_hc_baller_data_pending(&ctx->h3_baller, data)
|| cf_hc_baller_data_pending(&ctx->h21_baller, data);
for(i = 0; i < ctx->baller_count; i++)
if(cf_hc_baller_data_pending(&ctx->ballers[i], data))
return TRUE;
return FALSE;
}
static struct curltime cf_get_max_baller_time(struct Curl_cfilter *cf,
@@ -422,21 +468,17 @@ static struct curltime cf_get_max_baller_time(struct Curl_cfilter *cf,
int query)
{
struct cf_hc_ctx *ctx = cf->ctx;
struct Curl_cfilter *cfb;
struct curltime t, tmax;
size_t i;
memset(&tmax, 0, sizeof(tmax));
memset(&t, 0, sizeof(t));
cfb = ctx->h21_baller.enabled ? ctx->h21_baller.cf : NULL;
if(cfb && !cfb->cft->query(cfb, data, query, NULL, &t)) {
if((t.tv_sec || t.tv_usec) && Curl_timediff_us(t, tmax) > 0)
tmax = t;
}
memset(&t, 0, sizeof(t));
cfb = ctx->h3_baller.enabled ? ctx->h3_baller.cf : NULL;
if(cfb && !cfb->cft->query(cfb, data, query, NULL, &t)) {
if((t.tv_sec || t.tv_usec) && Curl_timediff_us(t, tmax) > 0)
tmax = t;
for(i = 0; i < ctx->baller_count; i++) {
struct Curl_cfilter *cfb = ctx->ballers[i].cf;
memset(&t, 0, sizeof(t));
if(cfb && !cfb->cft->query(cfb, data, query, NULL, &t)) {
if((t.tv_sec || t.tv_usec) && Curl_timediff_us(t, tmax) > 0)
tmax = t;
}
}
return tmax;
}
@@ -446,6 +488,7 @@ static CURLcode cf_hc_query(struct Curl_cfilter *cf,
int query, int *pres1, void *pres2)
{
struct cf_hc_ctx *ctx = cf->ctx;
size_t i;
if(!cf->connected) {
switch(query) {
@@ -460,11 +503,11 @@ static CURLcode cf_hc_query(struct Curl_cfilter *cf,
return CURLE_OK;
}
case CF_QUERY_NEED_FLUSH: {
if(cf_hc_baller_needs_flush(&ctx->h3_baller, data)
|| cf_hc_baller_needs_flush(&ctx->h21_baller, data)) {
*pres1 = TRUE;
return CURLE_OK;
}
for(i = 0; i < ctx->baller_count; i++)
if(cf_hc_baller_needs_flush(&ctx->ballers[i], data)) {
*pres1 = TRUE;
return CURLE_OK;
}
break;
}
default:
@@ -482,14 +525,17 @@ static CURLcode cf_hc_cntrl(struct Curl_cfilter *cf,
{
struct cf_hc_ctx *ctx = cf->ctx;
CURLcode result = CURLE_OK;
size_t i;
if(!cf->connected) {
result = cf_hc_baller_cntrl(&ctx->h3_baller, data, event, arg1, arg2);
if(!result || (result == CURLE_AGAIN))
result = cf_hc_baller_cntrl(&ctx->h21_baller, data, event, arg1, arg2);
if(result == CURLE_AGAIN)
result = CURLE_OK;
for(i = 0; i < ctx->baller_count; i++) {
result = cf_hc_baller_cntrl(&ctx->ballers[i], data, event, arg1, arg2);
if(result && (result != CURLE_AGAIN))
goto out;
}
result = CURLE_OK;
}
out:
return result;
}
@@ -537,23 +583,37 @@ struct Curl_cftype Curl_cft_http_connect = {
static CURLcode cf_hc_create(struct Curl_cfilter **pcf,
struct Curl_easy *data,
const struct Curl_dns_entry *remotehost,
bool try_h3, bool try_h21)
enum alpnid *alpnids, size_t alpn_count)
{
struct Curl_cfilter *cf = NULL;
struct cf_hc_ctx *ctx;
CURLcode result = CURLE_OK;
size_t i;
DEBUGASSERT(alpnids);
DEBUGASSERT(alpn_count);
DEBUGASSERT(alpn_count <= ARRAYSIZE(ctx->ballers));
if(!alpn_count || (alpn_count > ARRAYSIZE(ctx->ballers))) {
failf(data, "https-connect filter create with unsupported %zu ALPN ids",
alpn_count);
return CURLE_FAILED_INIT;
}
(void)data;
ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
ctx->remotehost = remotehost;
ctx->h3_baller.enabled = try_h3;
ctx->h21_baller.enabled = try_h21;
for(i = 0; i < alpn_count; ++i)
cf_hc_baller_assign(&ctx->ballers[i], alpnids[i]);
for(; i < ARRAYSIZE(ctx->ballers); ++i)
ctx->ballers[i].alpn_id = ALPN_none;
ctx->baller_count = alpn_count;
result = Curl_cf_create(&cf, &Curl_cft_http_connect, ctx);
CURL_TRC_CF(data, cf, "created with %zu ALPNs -> %d",
ctx->baller_count, result);
if(result)
goto out;
ctx = NULL;
@@ -569,13 +629,13 @@ static CURLcode cf_http_connect_add(struct Curl_easy *data,
struct connectdata *conn,
int sockindex,
const struct Curl_dns_entry *remotehost,
bool try_h3, bool try_h21)
enum alpnid *alpn_ids, size_t alpn_count)
{
struct Curl_cfilter *cf;
CURLcode result = CURLE_OK;
DEBUGASSERT(data);
result = cf_hc_create(&cf, data, remotehost, try_h3, try_h21);
result = cf_hc_create(&cf, data, remotehost, alpn_ids, alpn_count);
if(result)
goto out;
Curl_conn_cf_add(data, conn, sockindex, cf);
@@ -588,33 +648,88 @@ CURLcode Curl_cf_https_setup(struct Curl_easy *data,
int sockindex,
const struct Curl_dns_entry *remotehost)
{
bool try_h3 = FALSE, try_h21 = TRUE; /* defaults, for now */
enum alpnid alpn_ids[2];
size_t alpn_count = 0;
CURLcode result = CURLE_OK;
(void)sockindex;
(void)remotehost;
if(!conn->bits.tls_enable_alpn)
goto out;
if(data->state.httpwant == CURL_HTTP_VERSION_3ONLY) {
result = Curl_conn_may_http3(data, conn);
if(result) /* cannot do it */
goto out;
try_h3 = TRUE;
try_h21 = FALSE;
}
else if(data->state.httpwant >= CURL_HTTP_VERSION_3) {
/* We assume that silently not even trying H3 is ok here */
/* TODO: should we fail instead? */
try_h3 = (Curl_conn_may_http3(data, conn) == CURLE_OK);
try_h21 = TRUE;
if(conn->bits.tls_enable_alpn) {
switch(data->state.httpwant) {
case CURL_HTTP_VERSION_NONE:
/* No preferences by transfer setup. Choose best defaults */
#ifdef USE_HTTPSRR
if(conn->dns_entry && conn->dns_entry->hinfo &&
!conn->dns_entry->hinfo->no_def_alpn) {
size_t i, j;
for(i = 0; i < ARRAYSIZE(conn->dns_entry->hinfo->alpns) &&
alpn_count < ARRAYSIZE(alpn_ids); ++i) {
bool present = FALSE;
enum alpnid alpn = conn->dns_entry->hinfo->alpns[i];
for(j = 0; j < alpn_count; ++j) {
if(alpn == alpn_ids[j]) {
present = TRUE;
break;
}
}
if(!present) {
switch(alpn) {
case ALPN_h3:
if(Curl_conn_may_http3(data, conn))
break; /* not possible */
FALLTHROUGH();
case ALPN_h2:
case ALPN_h1:
alpn_ids[alpn_count++] = alpn;
break;
default: /* ignore */
break;
}
}
}
}
#endif
if(!alpn_count)
alpn_ids[alpn_count++] = ALPN_h2;
break;
case CURL_HTTP_VERSION_3ONLY:
result = Curl_conn_may_http3(data, conn);
if(result) /* cannot do it */
goto out;
alpn_ids[alpn_count++] = ALPN_h3;
break;
case CURL_HTTP_VERSION_3:
/* We assume that silently not even trying H3 is ok here */
/* TODO: should we fail instead? */
if(Curl_conn_may_http3(data, conn) == CURLE_OK)
alpn_ids[alpn_count++] = ALPN_h3;
alpn_ids[alpn_count++] = ALPN_h2;
break;
case CURL_HTTP_VERSION_2_0:
case CURL_HTTP_VERSION_2TLS:
case CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE:
alpn_ids[alpn_count++] = ALPN_h2;
break;
case CURL_HTTP_VERSION_1_0:
case CURL_HTTP_VERSION_1_1:
alpn_ids[alpn_count++] = ALPN_h1;
break;
default:
alpn_ids[alpn_count++] = ALPN_h2;
break;
}
}
/* If we identified ALPNs to use, install our filter. Otherwise,
* install nothing, so our call will use a default connect setup. */
if(alpn_count) {
result = cf_http_connect_add(data, conn, sockindex, remotehost,
alpn_ids, alpn_count);
}
result = cf_http_connect_add(data, conn, sockindex, remotehost,
try_h3, try_h21);
out:
return result;
}
#endif /* !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER) */
#endif /* !defined(CURL_DISABLE_HTTP) */

View File

@@ -25,7 +25,7 @@
***************************************************************************/
#include "curl_setup.h"
#if !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER)
#if !defined(CURL_DISABLE_HTTP)
struct Curl_cfilter;
struct Curl_easy;
@@ -54,5 +54,5 @@ CURLcode Curl_cf_https_setup(struct Curl_easy *data,
const struct Curl_dns_entry *remotehost);
#endif /* !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER) */
#endif /* !defined(CURL_DISABLE_HTTP) */
#endif /* HEADER_CURL_CF_HTTP_H */

View File

@@ -306,9 +306,9 @@ tcpkeepalive(struct Curl_easy *data,
* Assign the address `ai` to the Curl_sockaddr_ex `dest` and
* set the transport used.
*/
void Curl_sock_assign_addr(struct Curl_sockaddr_ex *dest,
const struct Curl_addrinfo *ai,
int transport)
CURLcode Curl_sock_assign_addr(struct Curl_sockaddr_ex *dest,
const struct Curl_addrinfo *ai,
int transport)
{
/*
* The Curl_sockaddr_ex structure is basically libcurl's external API
@@ -334,9 +334,13 @@ void Curl_sock_assign_addr(struct Curl_sockaddr_ex *dest,
}
dest->addrlen = (unsigned int)ai->ai_addrlen;
if(dest->addrlen > sizeof(struct Curl_sockaddr_storage))
dest->addrlen = sizeof(struct Curl_sockaddr_storage);
if(dest->addrlen > sizeof(struct Curl_sockaddr_storage)) {
DEBUGASSERT(0);
return CURLE_TOO_LARGE;
}
memcpy(&dest->curl_sa_addr, ai->ai_addr, dest->addrlen);
return CURLE_OK;
}
static CURLcode socket_open(struct Curl_easy *data,
@@ -395,12 +399,16 @@ CURLcode Curl_socket_open(struct Curl_easy *data,
curl_socket_t *sockfd)
{
struct Curl_sockaddr_ex dummy;
CURLcode result;
if(!addr)
/* if the caller does not want info back, use a local temp copy */
addr = &dummy;
Curl_sock_assign_addr(addr, ai, transport);
result = Curl_sock_assign_addr(addr, ai, transport);
if(result)
return result;
return socket_open(data, addr, sockfd);
}
@@ -959,14 +967,20 @@ struct cf_socket_ctx {
BIT(active);
};
static void cf_socket_ctx_init(struct cf_socket_ctx *ctx,
const struct Curl_addrinfo *ai,
int transport)
static CURLcode cf_socket_ctx_init(struct cf_socket_ctx *ctx,
const struct Curl_addrinfo *ai,
int transport)
{
CURLcode result;
memset(ctx, 0, sizeof(*ctx));
ctx->sock = CURL_SOCKET_BAD;
ctx->transport = transport;
Curl_sock_assign_addr(&ctx->addr, ai, transport);
result = Curl_sock_assign_addr(&ctx->addr, ai, transport);
if(result)
return result;
#ifdef DEBUGBUILD
{
char *p = getenv("CURL_DBG_SOCK_WBLOCK");
@@ -995,6 +1009,8 @@ static void cf_socket_ctx_init(struct cf_socket_ctx *ctx,
}
}
#endif
return result;
}
static void cf_socket_close(struct Curl_cfilter *cf, struct Curl_easy *data)
@@ -1282,7 +1298,7 @@ static int do_connect(struct Curl_cfilter *cf, struct Curl_easy *data,
rc = connect(ctx->sock, &ctx->addr.curl_sa_addr, ctx->addr.addrlen);
#elif defined(MSG_FASTOPEN) /* old Linux */
if(cf->conn->given->flags & PROTOPT_SSL)
if(Curl_conn_is_ssl(cf->conn, cf->sockindex))
rc = connect(ctx->sock, &ctx->addr.curl_sa_addr, ctx->addr.addrlen);
else
rc = 0; /* Do nothing */
@@ -1443,7 +1459,7 @@ static bool cf_socket_data_pending(struct Curl_cfilter *cf,
(void)data;
readable = SOCKET_READABLE(ctx->sock, 0);
return (readable > 0 && (readable & CURL_CSELECT_IN));
return readable > 0 && (readable & CURL_CSELECT_IN);
}
#ifdef USE_WINSOCK
@@ -1805,7 +1821,10 @@ CURLcode Curl_cf_tcp_create(struct Curl_cfilter **pcf,
result = CURLE_OUT_OF_MEMORY;
goto out;
}
cf_socket_ctx_init(ctx, ai, transport);
result = cf_socket_ctx_init(ctx, ai, transport);
if(result)
goto out;
result = Curl_cf_create(&cf, &Curl_cft_tcp, ctx);
@@ -1831,7 +1850,7 @@ static CURLcode cf_udp_setup_quic(struct Curl_cfilter *cf,
/* QUIC needs a connected socket, nonblocking */
DEBUGASSERT(ctx->sock != CURL_SOCKET_BAD);
rc = connect(ctx->sock, &ctx->addr.curl_sa_addr,
rc = connect(ctx->sock, &ctx->addr.curl_sa_addr, /* NOLINT FIXME */
(curl_socklen_t)ctx->addr.addrlen);
if(-1 == rc) {
return socket_connect_result(data, ctx->ip.remote_ip, SOCKERRNO);
@@ -1954,7 +1973,10 @@ CURLcode Curl_cf_udp_create(struct Curl_cfilter **pcf,
result = CURLE_OUT_OF_MEMORY;
goto out;
}
cf_socket_ctx_init(ctx, ai, transport);
result = cf_socket_ctx_init(ctx, ai, transport);
if(result)
goto out;
result = Curl_cf_create(&cf, &Curl_cft_udp, ctx);
@@ -2006,7 +2028,10 @@ CURLcode Curl_cf_unix_create(struct Curl_cfilter **pcf,
result = CURLE_OUT_OF_MEMORY;
goto out;
}
cf_socket_ctx_init(ctx, ai, transport);
result = cf_socket_ctx_init(ctx, ai, transport);
if(result)
goto out;
result = Curl_cf_create(&cf, &Curl_cft_unix, ctx);

View File

@@ -95,9 +95,9 @@ void Curl_sndbuf_init(curl_socket_t sockfd);
* Assign the address `ai` to the Curl_sockaddr_ex `dest` and
* set the transport used.
*/
void Curl_sock_assign_addr(struct Curl_sockaddr_ex *dest,
const struct Curl_addrinfo *ai,
int transport);
CURLcode Curl_sock_assign_addr(struct Curl_sockaddr_ex *dest,
const struct Curl_addrinfo *ai,
int transport);
/**
* Creates a cfilter that opens a TCP socket to the given address

View File

@@ -494,13 +494,35 @@ bool Curl_conn_is_multiplex(struct connectdata *conn, int sockindex)
for(; cf; cf = cf->next) {
if(cf->cft->flags & CF_TYPE_MULTIPLEX)
return TRUE;
if(cf->cft->flags & CF_TYPE_IP_CONNECT
|| cf->cft->flags & CF_TYPE_SSL)
if(cf->cft->flags & (CF_TYPE_IP_CONNECT|CF_TYPE_SSL))
return FALSE;
}
return FALSE;
}
unsigned char Curl_conn_http_version(struct Curl_easy *data)
{
struct Curl_cfilter *cf;
CURLcode result = CURLE_UNKNOWN_OPTION;
unsigned char v = 0;
cf = data->conn ? data->conn->cfilter[FIRSTSOCKET] : NULL;
for(; cf; cf = cf->next) {
if(cf->cft->flags & CF_TYPE_HTTP) {
int value = 0;
result = cf->cft->query(cf, data, CF_QUERY_HTTP_VERSION, &value, NULL);
if(!result && ((value < 0) || (value > 255)))
result = CURLE_FAILED_INIT;
else
v = (unsigned char)value;
break;
}
if(cf->cft->flags & (CF_TYPE_IP_CONNECT|CF_TYPE_SSL))
break;
}
return (unsigned char)(result ? 0 : v);
}
bool Curl_conn_data_pending(struct Curl_easy *data, int sockindex)
{
struct Curl_cfilter *cf;
@@ -711,18 +733,6 @@ static CURLcode cf_cntrl_all(struct connectdata *conn,
return result;
}
void Curl_conn_ev_data_attach(struct connectdata *conn,
struct Curl_easy *data)
{
cf_cntrl_all(conn, data, TRUE, CF_CTRL_DATA_ATTACH, 0, NULL);
}
void Curl_conn_ev_data_detach(struct connectdata *conn,
struct Curl_easy *data)
{
cf_cntrl_all(conn, data, TRUE, CF_CTRL_DATA_DETACH, 0, NULL);
}
CURLcode Curl_conn_ev_data_setup(struct Curl_easy *data)
{
return cf_cntrl_all(data->conn, data, FALSE,

View File

@@ -132,8 +132,6 @@ typedef CURLcode Curl_cft_conn_keep_alive(struct Curl_cfilter *cf,
* to all filters in the chain. Overall result is always CURLE_OK.
*/
/* data event arg1 arg2 return */
#define CF_CTRL_DATA_ATTACH 1 /* 0 NULL ignored */
#define CF_CTRL_DATA_DETACH 2 /* 0 NULL ignored */
#define CF_CTRL_DATA_SETUP 4 /* 0 NULL first fail */
#define CF_CTRL_DATA_IDLE 5 /* 0 NULL first fail */
#define CF_CTRL_DATA_PAUSE 6 /* on/off NULL first fail */
@@ -178,6 +176,7 @@ typedef CURLcode Curl_cft_cntrl(struct Curl_cfilter *cf,
#define CF_QUERY_STREAM_ERROR 6 /* error code - */
#define CF_QUERY_NEED_FLUSH 7 /* TRUE/FALSE - */
#define CF_QUERY_IP_INFO 8 /* TRUE/FALSE struct ip_quadruple */
#define CF_QUERY_HTTP_VERSION 9 /* number (10/11/20/30) - */
/**
* Query the cfilter for properties. Filters ignorant of a query will
@@ -197,11 +196,13 @@ typedef CURLcode Curl_cft_query(struct Curl_cfilter *cf,
* CF_TYPE_SSL: provide SSL/TLS
* CF_TYPE_MULTIPLEX: provides multiplexing of easy handles
* CF_TYPE_PROXY provides proxying
* CF_TYPE_HTTP implement a version of the HTTP protocol
*/
#define CF_TYPE_IP_CONNECT (1 << 0)
#define CF_TYPE_SSL (1 << 1)
#define CF_TYPE_MULTIPLEX (1 << 2)
#define CF_TYPE_PROXY (1 << 3)
#define CF_TYPE_HTTP (1 << 4)
/* A connection filter type, e.g. specific implementation. */
struct Curl_cftype {
@@ -394,6 +395,12 @@ bool Curl_conn_is_ssl(struct connectdata *conn, int sockindex);
*/
bool Curl_conn_is_multiplex(struct connectdata *conn, int sockindex);
/**
* Return the HTTP version used on the FIRSTSOCKET connection filters
* or 0 if unknown. Value otherwise is 09, 10, 11, etc.
*/
unsigned char Curl_conn_http_version(struct Curl_easy *data);
/**
* Close the filter chain at `sockindex` for connection `data->conn`.
* Filters remain in place and may be connected again afterwards.
@@ -476,24 +483,6 @@ ssize_t Curl_cf_recv(struct Curl_easy *data, int sockindex, char *buf,
ssize_t Curl_cf_send(struct Curl_easy *data, int sockindex,
const void *buf, size_t len, bool eos, CURLcode *code);
/**
* The easy handle `data` is being attached to `conn`. This does
* not mean that data will actually do a transfer. Attachment is
* also used for temporary actions on the connection.
*/
void Curl_conn_ev_data_attach(struct connectdata *conn,
struct Curl_easy *data);
/**
* The easy handle `data` is being detached (no longer served)
* by connection `conn`. All filters are informed to release any resources
* related to `data`.
* Note: there may be several `data` attached to a connection at the same
* time.
*/
void Curl_conn_ev_data_detach(struct connectdata *conn,
struct Curl_easy *data);
/**
* Notify connection filters that they need to setup data for
* a transfer.

View File

@@ -100,6 +100,8 @@ static void cpool_shutdown_all(struct cpool *cpool,
struct Curl_easy *data, int timeout_ms);
static void cpool_close_and_destroy_all(struct cpool *cpool);
static struct connectdata *cpool_get_oldest_idle(struct cpool *cpool);
static size_t cpool_shutdown_dest_count(struct cpool *cpool,
const char *destination);
static struct cpool_bundle *cpool_bundle_create(const char *dest,
size_t dest_len)
@@ -285,6 +287,7 @@ int Curl_cpool_check_limits(struct Curl_easy *data,
struct cpool_bundle *bundle;
size_t dest_limit = 0;
size_t total_limit = 0;
size_t shutdowns;
int result = CPOOL_LIMIT_OK;
if(!cpool)
@@ -300,8 +303,12 @@ int Curl_cpool_check_limits(struct Curl_easy *data,
CPOOL_LOCK(cpool);
if(dest_limit) {
size_t live;
bundle = cpool_find_bundle(cpool, conn);
while(bundle && (Curl_llist_count(&bundle->conns) >= dest_limit)) {
live = bundle ? Curl_llist_count(&bundle->conns) : 0;
shutdowns = cpool_shutdown_dest_count(cpool, conn->destination);
while(!shutdowns && bundle && live >= dest_limit) {
struct connectdata *oldest_idle = NULL;
/* The bundle is full. Extract the oldest connection that may
* be removed now, if there is one. */
@@ -317,15 +324,18 @@ int Curl_cpool_check_limits(struct Curl_easy *data,
/* in case the bundle was destroyed in disconnect, look it up again */
bundle = cpool_find_bundle(cpool, conn);
live = bundle ? Curl_llist_count(&bundle->conns) : 0;
shutdowns = cpool_shutdown_dest_count(cpool, conn->destination);
}
if(bundle && (Curl_llist_count(&bundle->conns) >= dest_limit)) {
if((live + shutdowns) >= dest_limit) {
result = CPOOL_LIMIT_DEST;
goto out;
}
}
if(total_limit) {
while(cpool->num_conn >= total_limit) {
shutdowns = Curl_llist_count(&cpool->shutdowns);
while((cpool->num_conn + shutdowns) >= total_limit) {
struct connectdata *oldest_idle = cpool_get_oldest_idle(cpool);
if(!oldest_idle)
break;
@@ -335,8 +345,9 @@ int Curl_cpool_check_limits(struct Curl_easy *data,
"limit of %zu",
oldest_idle->connection_id, cpool->num_conn, total_limit));
Curl_cpool_disconnect(data, oldest_idle, FALSE);
shutdowns = Curl_llist_count(&cpool->shutdowns);
}
if(cpool->num_conn >= total_limit) {
if((cpool->num_conn + shutdowns) >= total_limit) {
result = CPOOL_LIMIT_TOTAL;
goto out;
}
@@ -374,7 +385,8 @@ CURLcode Curl_cpool_add_conn(struct Curl_easy *data,
cpool->num_conn++;
DEBUGF(infof(data, "Added connection %" FMT_OFF_T ". "
"The cache now contains %zu members",
conn->connection_id, cpool->num_conn));
conn->connection_id,
cpool->num_conn + Curl_llist_count(&cpool->shutdowns)));
out:
CPOOL_UNLOCK(cpool);
@@ -612,6 +624,21 @@ bool Curl_cpool_find(struct Curl_easy *data,
return result;
}
/* How many connections to the given destination are in shutdown? */
static size_t cpool_shutdown_dest_count(struct cpool *cpool,
const char *destination)
{
size_t n = 0;
struct Curl_llist_node *e = Curl_llist_head(&cpool->shutdowns);
while(e) {
struct connectdata *conn = Curl_node_elem(e);
if(!strcmp(destination, conn->destination))
++n;
e = Curl_node_next(e);
}
return n;
}
static void cpool_shutdown_discard_all(struct cpool *cpool)
{
struct Curl_llist_node *e = Curl_llist_head(&cpool->shutdowns);
@@ -742,12 +769,12 @@ static void cpool_discard_conn(struct cpool *cpool,
/* Add the connection to our shutdown list for non-blocking shutdown
* during multi processing. */
if(data->multi && data->multi->max_shutdown_connections > 0 &&
(data->multi->max_shutdown_connections >=
(long)Curl_llist_count(&cpool->shutdowns))) {
if(data->multi && data->multi->max_total_connections > 0 &&
(data->multi->max_total_connections <=
(long)(cpool->num_conn + Curl_llist_count(&cpool->shutdowns)))) {
DEBUGF(infof(data, "[CCACHE] discarding oldest shutdown connection "
"due to limit of %ld",
data->multi->max_shutdown_connections));
"due to connection limit of %ld",
data->multi->max_total_connections));
cpool_shutdown_destroy_oldest(cpool);
}
@@ -767,8 +794,8 @@ static void cpool_discard_conn(struct cpool *cpool,
Curl_llist_append(&cpool->shutdowns, conn, &conn->cpool_node);
DEBUGF(infof(data, "[CCACHE] added #%" FMT_OFF_T
" to shutdown list of length %zu", conn->connection_id,
Curl_llist_count(&cpool->shutdowns)));
" to shutdowns, now %zu conns in shutdown",
conn->connection_id, Curl_llist_count(&cpool->shutdowns)));
}
void Curl_cpool_disconnect(struct Curl_easy *data,
@@ -926,10 +953,11 @@ CURLcode Curl_cpool_add_pollfds(struct cpool *cpool,
return result;
}
CURLcode Curl_cpool_add_waitfds(struct cpool *cpool,
struct curl_waitfds *cwfds)
/* return information about the shutdown connections */
unsigned int Curl_cpool_add_waitfds(struct cpool *cpool,
struct Curl_waitfds *cwfds)
{
CURLcode result = CURLE_OK;
unsigned int need = 0;
CPOOL_LOCK(cpool);
if(Curl_llist_head(&cpool->shutdowns)) {
@@ -945,14 +973,51 @@ CURLcode Curl_cpool_add_waitfds(struct cpool *cpool,
Curl_conn_adjust_pollset(cpool->idata, &ps);
Curl_detach_connection(cpool->idata);
result = Curl_waitfds_add_ps(cwfds, &ps);
if(result)
goto out;
need += Curl_waitfds_add_ps(cwfds, &ps);
}
}
CPOOL_UNLOCK(cpool);
return need;
}
/* return fd_set info about the shutdown connections */
void Curl_cpool_setfds(struct cpool *cpool,
fd_set *read_fd_set, fd_set *write_fd_set,
int *maxfd)
{
CPOOL_LOCK(cpool);
if(Curl_llist_head(&cpool->shutdowns)) {
struct Curl_llist_node *e;
for(e = Curl_llist_head(&cpool->shutdowns); e;
e = Curl_node_next(e)) {
struct easy_pollset ps;
unsigned int i;
struct connectdata *conn = Curl_node_elem(e);
memset(&ps, 0, sizeof(ps));
Curl_attach_connection(cpool->idata, conn);
Curl_conn_adjust_pollset(cpool->idata, &ps);
Curl_detach_connection(cpool->idata);
for(i = 0; i < ps.num; i++) {
#if defined(__DJGPP__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Warith-conversion"
#endif
if(ps.actions[i] & CURL_POLL_IN)
FD_SET(ps.sockets[i], read_fd_set);
if(ps.actions[i] & CURL_POLL_OUT)
FD_SET(ps.sockets[i], write_fd_set);
#if defined(__DJGPP__)
#pragma GCC diagnostic pop
#endif
if((ps.actions[i] & (CURL_POLL_OUT | CURL_POLL_IN)) &&
((int)ps.sockets[i] > *maxfd))
*maxfd = (int)ps.sockets[i];
}
}
}
out:
CPOOL_UNLOCK(cpool);
return result;
}
static void cpool_perform(struct cpool *cpool)
@@ -1052,6 +1117,11 @@ static void cpool_close_and_destroy(struct cpool *cpool,
Curl_detach_connection(data);
Curl_conn_free(data, conn);
if(cpool && cpool->multi) {
DEBUGF(infof(data, "[CCACHE] trigger multi connchanged"));
Curl_multi_connchanged(cpool->multi);
}
}

View File

@@ -31,7 +31,7 @@
struct connectdata;
struct Curl_easy;
struct curl_pollfds;
struct curl_waitfds;
struct Curl_waitfds;
struct Curl_multi;
struct Curl_share;
@@ -113,8 +113,6 @@ typedef bool Curl_cpool_done_match_cb(bool result, void *userdata);
* @param dest_len destination length, including terminating NUL
* @param conn_cb must be present, called for each connection in the
* bundle until it returns TRUE
* @param result_cb if not NULL, is called at the end with the result
* of the `conn_cb` or FALSE if never called.
* @return combined result of last conn_db and result_cb or FALSE if no
connections were present.
*/
@@ -185,8 +183,12 @@ void Curl_cpool_do_locked(struct Curl_easy *data,
*/
CURLcode Curl_cpool_add_pollfds(struct cpool *connc,
struct curl_pollfds *cpfds);
CURLcode Curl_cpool_add_waitfds(struct cpool *connc,
struct curl_waitfds *cwfds);
unsigned int Curl_cpool_add_waitfds(struct cpool *connc,
struct Curl_waitfds *cwfds);
void Curl_cpool_setfds(struct cpool *cpool,
fd_set *read_fd_set, fd_set *write_fd_set,
int *maxfd);
/**
* Perform maintenance on connections in the pool. Specifically,

View File

@@ -78,6 +78,7 @@
#include "vquic/vquic.h" /* for quic cfilters */
#include "http_proxy.h"
#include "socks.h"
#include "strcase.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -88,6 +89,27 @@
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
#endif
#if !defined(CURL_DISABLE_ALTSVC) || defined(USE_HTTPSRR)
enum alpnid Curl_alpn2alpnid(char *name, size_t len)
{
if(len == 2) {
if(strncasecompare(name, "h1", 2))
return ALPN_h1;
if(strncasecompare(name, "h2", 2))
return ALPN_h2;
if(strncasecompare(name, "h3", 2))
return ALPN_h3;
}
else if(len == 8) {
if(strncasecompare(name, "http/1.1", 8))
return ALPN_h1;
}
return ALPN_none; /* unknown, probably rubbish input */
}
#endif
/*
* Curl_timeleft() returns the amount of milliseconds left allowed for the
* transfer/connection. If the value is 0, there is no timeout (ie there is
@@ -1485,7 +1507,7 @@ CURLcode Curl_conn_setup(struct Curl_easy *data,
DEBUGASSERT(data);
DEBUGASSERT(conn->handler);
#if !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER)
#if !defined(CURL_DISABLE_HTTP)
if(!conn->cfilter[sockindex] &&
conn->handler->protocol == CURLPROTO_HTTPS) {
DEBUGASSERT(ssl_mode != CURL_CF_SSL_DISABLE);
@@ -1493,7 +1515,7 @@ CURLcode Curl_conn_setup(struct Curl_easy *data,
if(result)
goto out;
}
#endif /* !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER) */
#endif /* !defined(CURL_DISABLE_HTTP) */
/* Still no cfilter set, apply default. */
if(!conn->cfilter[sockindex]) {

View File

@@ -32,6 +32,8 @@
struct Curl_dns_entry;
struct ip_quadruple;
enum alpnid Curl_alpn2alpnid(char *name, size_t len);
/* generic function that returns how much time there is left to run, according
to the timeouts set */
timediff_t Curl_timeleft(struct Curl_easy *data,

View File

@@ -65,34 +65,15 @@
/* allow no more than 5 "chained" compression steps */
#define MAX_ENCODE_STACK 5
#define DSIZ CURL_MAX_WRITE_SIZE /* buffer size for decompressed data */
#define DECOMPRESS_BUFFER_SIZE 16384 /* buffer size for decompressed data */
#ifdef HAVE_LIBZ
/* Comment this out if zlib is always going to be at least ver. 1.2.0.4
(doing so will reduce code size slightly). */
#define OLD_ZLIB_SUPPORT 1
#define GZIP_MAGIC_0 0x1f
#define GZIP_MAGIC_1 0x8b
/* gzip flag byte */
#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */
#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
#define ORIG_NAME 0x08 /* bit 3 set: original filename present */
#define COMMENT 0x10 /* bit 4 set: file comment present */
#define RESERVED 0xE0 /* bits 5..7: reserved */
typedef enum {
ZLIB_UNINIT, /* uninitialized */
ZLIB_INIT, /* initialized */
ZLIB_INFLATING, /* inflating started. */
ZLIB_EXTERNAL_TRAILER, /* reading external trailer */
ZLIB_GZIP_HEADER, /* reading gzip header */
ZLIB_GZIP_INFLATING, /* inflating gzip stream */
ZLIB_INIT_GZIP /* initialized in transparent gzip mode */
} zlibInitState;
@@ -100,6 +81,7 @@ typedef enum {
struct zlib_writer {
struct Curl_cwriter super;
zlibInitState zlib_init; /* zlib init state */
char buffer[DECOMPRESS_BUFFER_SIZE]; /* Put the decompressed data here. */
uInt trailerlen; /* Remaining trailer byte count. */
z_stream z; /* State structure for zlib. */
};
@@ -137,9 +119,6 @@ static CURLcode
exit_zlib(struct Curl_easy *data,
z_stream *z, zlibInitState *zlib_init, CURLcode result)
{
if(*zlib_init == ZLIB_GZIP_HEADER)
Curl_safefree(z->next_in);
if(*zlib_init != ZLIB_UNINIT) {
if(inflateEnd(z) != Z_OK && result == CURLE_OK)
result = process_zlib_error(data, z);
@@ -183,21 +162,13 @@ static CURLcode inflate_stream(struct Curl_easy *data,
Bytef *orig_in = z->next_in;
bool done = FALSE;
CURLcode result = CURLE_OK; /* Curl_client_write status */
char *decomp; /* Put the decompressed data here. */
/* Check state. */
if(zp->zlib_init != ZLIB_INIT &&
zp->zlib_init != ZLIB_INFLATING &&
zp->zlib_init != ZLIB_INIT_GZIP &&
zp->zlib_init != ZLIB_GZIP_INFLATING)
zp->zlib_init != ZLIB_INIT_GZIP)
return exit_zlib(data, z, &zp->zlib_init, CURLE_WRITE_ERROR);
/* Dynamically allocate a buffer for decompression because it is uncommonly
large to hold on the stack */
decomp = malloc(DSIZ);
if(!decomp)
return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
/* because the buffer size is fixed, iteratively decompress and transfer to
the client via next_write function. */
while(!done) {
@@ -205,8 +176,8 @@ static CURLcode inflate_stream(struct Curl_easy *data,
done = TRUE;
/* (re)set buffer for decompressed output for every iteration */
z->next_out = (Bytef *) decomp;
z->avail_out = DSIZ;
z->next_out = (Bytef *) zp->buffer;
z->avail_out = DECOMPRESS_BUFFER_SIZE;
#ifdef Z_BLOCK
/* Z_BLOCK is only available in zlib ver. >= 1.2.0.5 */
@@ -217,11 +188,11 @@ static CURLcode inflate_stream(struct Curl_easy *data,
#endif
/* Flush output data if some. */
if(z->avail_out != DSIZ) {
if(z->avail_out != DECOMPRESS_BUFFER_SIZE) {
if(status == Z_OK || status == Z_STREAM_END) {
zp->zlib_init = started; /* Data started. */
result = Curl_cwriter_write(data, writer->next, type, decomp,
DSIZ - z->avail_out);
result = Curl_cwriter_write(data, writer->next, type, zp->buffer,
DECOMPRESS_BUFFER_SIZE - z->avail_out);
if(result) {
exit_zlib(data, z, &zp->zlib_init, result);
break;
@@ -264,7 +235,6 @@ static CURLcode inflate_stream(struct Curl_easy *data,
break;
}
}
free(decomp);
/* We are about to leave this call so the `nread' data bytes will not be seen
again. If we are in a state that would wrongly allow restart in raw mode
@@ -278,7 +248,7 @@ static CURLcode inflate_stream(struct Curl_easy *data,
/* Deflate handler. */
static CURLcode deflate_do_init(struct Curl_easy *data,
struct Curl_cwriter *writer)
struct Curl_cwriter *writer)
{
struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
@@ -294,8 +264,8 @@ static CURLcode deflate_do_init(struct Curl_easy *data,
}
static CURLcode deflate_do_write(struct Curl_easy *data,
struct Curl_cwriter *writer, int type,
const char *buf, size_t nbytes)
struct Curl_cwriter *writer, int type,
const char *buf, size_t nbytes)
{
struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
@@ -315,7 +285,7 @@ static CURLcode deflate_do_write(struct Curl_easy *data,
}
static void deflate_do_close(struct Curl_easy *data,
struct Curl_cwriter *writer)
struct Curl_cwriter *writer)
{
struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
@@ -335,124 +305,34 @@ static const struct Curl_cwtype deflate_encoding = {
/* Gzip handler. */
static CURLcode gzip_do_init(struct Curl_easy *data,
struct Curl_cwriter *writer)
struct Curl_cwriter *writer)
{
struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
const char *v = zlibVersion();
/* Initialize zlib */
z->zalloc = (alloc_func) zalloc_cb;
z->zfree = (free_func) zfree_cb;
if(strcmp(zlibVersion(), "1.2.0.4") >= 0) {
/* zlib ver. >= 1.2.0.4 supports transparent gzip decompressing */
if(strcmp(v, "1.2.0.4") >= 0) {
/* zlib version >= 1.2.0.4 supports transparent gzip decompressing */
if(inflateInit2(z, MAX_WBITS + 32) != Z_OK) {
return process_zlib_error(data, z);
}
zp->zlib_init = ZLIB_INIT_GZIP; /* Transparent gzip decompress state */
}
else {
/* we must parse the gzip header and trailer ourselves */
if(inflateInit2(z, -MAX_WBITS) != Z_OK) {
return process_zlib_error(data, z);
}
zp->trailerlen = 8; /* A CRC-32 and a 32-bit input size (RFC 1952, 2.2) */
zp->zlib_init = ZLIB_INIT; /* Initial call state */
failf(data, "too old zlib version: %s", v);
return CURLE_FAILED_INIT;
}
return CURLE_OK;
}
#ifdef OLD_ZLIB_SUPPORT
/* Skip over the gzip header */
typedef enum {
GZIP_OK,
GZIP_BAD,
GZIP_UNDERFLOW
} gzip_status;
static gzip_status check_gzip_header(unsigned char const *data, ssize_t len,
ssize_t *headerlen)
{
int method, flags;
const ssize_t totallen = len;
/* The shortest header is 10 bytes */
if(len < 10)
return GZIP_UNDERFLOW;
if((data[0] != GZIP_MAGIC_0) || (data[1] != GZIP_MAGIC_1))
return GZIP_BAD;
method = data[2];
flags = data[3];
if(method != Z_DEFLATED || (flags & RESERVED) != 0) {
/* cannot handle this compression method or unknown flag */
return GZIP_BAD;
}
/* Skip over time, xflags, OS code and all previous bytes */
len -= 10;
data += 10;
if(flags & EXTRA_FIELD) {
ssize_t extra_len;
if(len < 2)
return GZIP_UNDERFLOW;
extra_len = (data[1] << 8) | data[0];
if(len < (extra_len + 2))
return GZIP_UNDERFLOW;
len -= (extra_len + 2);
data += (extra_len + 2);
}
if(flags & ORIG_NAME) {
/* Skip over NUL-terminated filename */
while(len && *data) {
--len;
++data;
}
if(!len || *data)
return GZIP_UNDERFLOW;
/* Skip over the NUL */
--len;
++data;
}
if(flags & COMMENT) {
/* Skip over NUL-terminated comment */
while(len && *data) {
--len;
++data;
}
if(!len || *data)
return GZIP_UNDERFLOW;
/* Skip over the NUL */
--len;
}
if(flags & HEAD_CRC) {
if(len < 2)
return GZIP_UNDERFLOW;
len -= 2;
}
*headerlen = totallen - len;
return GZIP_OK;
}
#endif
static CURLcode gzip_do_write(struct Curl_easy *data,
struct Curl_cwriter *writer, int type,
const char *buf, size_t nbytes)
struct Curl_cwriter *writer, int type,
const char *buf, size_t nbytes)
{
struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */
@@ -468,117 +348,8 @@ static CURLcode gzip_do_write(struct Curl_easy *data,
return inflate_stream(data, writer, type, ZLIB_INIT_GZIP);
}
#ifndef OLD_ZLIB_SUPPORT
/* Support for old zlib versions is compiled away and we are running with
an old version, so return an error. */
/* We are running with an old version: return error. */
return exit_zlib(data, z, &zp->zlib_init, CURLE_WRITE_ERROR);
#else
/* This next mess is to get around the potential case where there is not
* enough data passed in to skip over the gzip header. If that happens, we
* malloc a block and copy what we have then wait for the next call. If
* there still is not enough (this is definitely a worst-case scenario), we
* make the block bigger, copy the next part in and keep waiting.
*
* This is only required with zlib versions < 1.2.0.4 as newer versions
* can handle the gzip header themselves.
*/
switch(zp->zlib_init) {
/* Skip over gzip header? */
case ZLIB_INIT:
{
/* Initial call state */
ssize_t hlen;
switch(check_gzip_header((unsigned char *) buf, nbytes, &hlen)) {
case GZIP_OK:
z->next_in = (Bytef *) buf + hlen;
z->avail_in = (uInt) (nbytes - hlen);
zp->zlib_init = ZLIB_GZIP_INFLATING; /* Inflating stream state */
break;
case GZIP_UNDERFLOW:
/* We need more data so we can find the end of the gzip header. it is
* possible that the memory block we malloc here will never be freed if
* the transfer abruptly aborts after this point. Since it is unlikely
* that circumstances will be right for this code path to be followed in
* the first place, and it is even more unlikely for a transfer to fail
* immediately afterwards, it should seldom be a problem.
*/
z->avail_in = (uInt) nbytes;
z->next_in = malloc(z->avail_in);
if(!z->next_in) {
return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
}
memcpy(z->next_in, buf, z->avail_in);
zp->zlib_init = ZLIB_GZIP_HEADER; /* Need more gzip header data state */
/* We do not have any data to inflate yet */
return CURLE_OK;
case GZIP_BAD:
default:
return exit_zlib(data, z, &zp->zlib_init, process_zlib_error(data, z));
}
}
break;
case ZLIB_GZIP_HEADER:
{
/* Need more gzip header data state */
ssize_t hlen;
z->avail_in += (uInt) nbytes;
z->next_in = Curl_saferealloc(z->next_in, z->avail_in);
if(!z->next_in) {
return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
}
/* Append the new block of data to the previous one */
memcpy(z->next_in + z->avail_in - nbytes, buf, nbytes);
switch(check_gzip_header(z->next_in, (ssize_t)z->avail_in, &hlen)) {
case GZIP_OK:
/* This is the zlib stream data */
free(z->next_in);
/* Do not point into the malloced block since we just freed it */
z->next_in = (Bytef *) buf + hlen + nbytes - z->avail_in;
z->avail_in = z->avail_in - (uInt)hlen;
zp->zlib_init = ZLIB_GZIP_INFLATING; /* Inflating stream state */
break;
case GZIP_UNDERFLOW:
/* We still do not have any data to inflate! */
return CURLE_OK;
case GZIP_BAD:
default:
return exit_zlib(data, z, &zp->zlib_init, process_zlib_error(data, z));
}
}
break;
case ZLIB_EXTERNAL_TRAILER:
z->next_in = (Bytef *) buf;
z->avail_in = (uInt) nbytes;
return process_trailer(data, zp);
case ZLIB_GZIP_INFLATING:
default:
/* Inflating stream state */
z->next_in = (Bytef *) buf;
z->avail_in = (uInt) nbytes;
break;
}
if(z->avail_in == 0) {
/* We do not have any data to inflate; wait until next time */
return CURLE_OK;
}
/* We have parsed the header, now uncompress the data */
return inflate_stream(data, writer, type, ZLIB_GZIP_INFLATING);
#endif
}
static void gzip_do_close(struct Curl_easy *data,
@@ -601,11 +372,11 @@ static const struct Curl_cwtype gzip_encoding = {
#endif /* HAVE_LIBZ */
#ifdef HAVE_BROTLI
/* Brotli writer. */
struct brotli_writer {
struct Curl_cwriter super;
char buffer[DECOMPRESS_BUFFER_SIZE];
BrotliDecoderState *br; /* State structure for brotli. */
};
@@ -648,7 +419,7 @@ static CURLcode brotli_map_error(BrotliDecoderErrorCode be)
}
static CURLcode brotli_do_init(struct Curl_easy *data,
struct Curl_cwriter *writer)
struct Curl_cwriter *writer)
{
struct brotli_writer *bp = (struct brotli_writer *) writer;
(void) data;
@@ -658,12 +429,11 @@ static CURLcode brotli_do_init(struct Curl_easy *data,
}
static CURLcode brotli_do_write(struct Curl_easy *data,
struct Curl_cwriter *writer, int type,
const char *buf, size_t nbytes)
struct Curl_cwriter *writer, int type,
const char *buf, size_t nbytes)
{
struct brotli_writer *bp = (struct brotli_writer *) writer;
const uint8_t *src = (const uint8_t *) buf;
char *decomp;
uint8_t *dst;
size_t dstleft;
CURLcode result = CURLE_OK;
@@ -675,18 +445,14 @@ static CURLcode brotli_do_write(struct Curl_easy *data,
if(!bp->br)
return CURLE_WRITE_ERROR; /* Stream already ended. */
decomp = malloc(DSIZ);
if(!decomp)
return CURLE_OUT_OF_MEMORY;
while((nbytes || r == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) &&
result == CURLE_OK) {
dst = (uint8_t *) decomp;
dstleft = DSIZ;
dst = (uint8_t *) bp->buffer;
dstleft = DECOMPRESS_BUFFER_SIZE;
r = BrotliDecoderDecompressStream(bp->br,
&nbytes, &src, &dstleft, &dst, NULL);
result = Curl_cwriter_write(data, writer->next, type,
decomp, DSIZ - dstleft);
bp->buffer, DECOMPRESS_BUFFER_SIZE - dstleft);
if(result)
break;
switch(r) {
@@ -704,7 +470,6 @@ static CURLcode brotli_do_write(struct Curl_easy *data,
break;
}
}
free(decomp);
return result;
}
@@ -712,7 +477,6 @@ static void brotli_do_close(struct Curl_easy *data,
struct Curl_cwriter *writer)
{
struct brotli_writer *bp = (struct brotli_writer *) writer;
(void) data;
if(bp->br) {
@@ -731,30 +495,51 @@ static const struct Curl_cwtype brotli_encoding = {
};
#endif
#ifdef HAVE_ZSTD
/* Zstd writer. */
struct zstd_writer {
struct Curl_cwriter super;
ZSTD_DStream *zds; /* State structure for zstd. */
void *decomp;
char buffer[DECOMPRESS_BUFFER_SIZE];
};
#ifdef ZSTD_STATIC_LINKING_ONLY
static void *Curl_zstd_alloc(void *opaque, size_t size)
{
(void)opaque;
return Curl_cmalloc(size);
}
static void Curl_zstd_free(void *opaque, void *address)
{
(void)opaque;
Curl_cfree(address);
}
#endif
static CURLcode zstd_do_init(struct Curl_easy *data,
struct Curl_cwriter *writer)
struct Curl_cwriter *writer)
{
struct zstd_writer *zp = (struct zstd_writer *) writer;
(void)data;
#ifdef ZSTD_STATIC_LINKING_ONLY
zp->zds = ZSTD_createDStream_advanced((ZSTD_customMem) {
.customAlloc = Curl_zstd_alloc,
.customFree = Curl_zstd_free,
.opaque = NULL
});
#else
zp->zds = ZSTD_createDStream();
zp->decomp = NULL;
#endif
return zp->zds ? CURLE_OK : CURLE_OUT_OF_MEMORY;
}
static CURLcode zstd_do_write(struct Curl_easy *data,
struct Curl_cwriter *writer, int type,
const char *buf, size_t nbytes)
struct Curl_cwriter *writer, int type,
const char *buf, size_t nbytes)
{
CURLcode result = CURLE_OK;
struct zstd_writer *zp = (struct zstd_writer *) writer;
@@ -765,19 +550,14 @@ static CURLcode zstd_do_write(struct Curl_easy *data,
if(!(type & CLIENTWRITE_BODY) || !nbytes)
return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
if(!zp->decomp) {
zp->decomp = malloc(DSIZ);
if(!zp->decomp)
return CURLE_OUT_OF_MEMORY;
}
in.pos = 0;
in.src = buf;
in.size = nbytes;
for(;;) {
out.pos = 0;
out.dst = zp->decomp;
out.size = DSIZ;
out.dst = zp->buffer;
out.size = DECOMPRESS_BUFFER_SIZE;
errorCode = ZSTD_decompressStream(zp->zds, &out, &in);
if(ZSTD_isError(errorCode)) {
@@ -785,7 +565,7 @@ static CURLcode zstd_do_write(struct Curl_easy *data,
}
if(out.pos > 0) {
result = Curl_cwriter_write(data, writer->next, type,
zp->decomp, out.pos);
zp->buffer, out.pos);
if(result)
break;
}
@@ -800,13 +580,8 @@ static void zstd_do_close(struct Curl_easy *data,
struct Curl_cwriter *writer)
{
struct zstd_writer *zp = (struct zstd_writer *) writer;
(void)data;
if(zp->decomp) {
free(zp->decomp);
zp->decomp = NULL;
}
if(zp->zds) {
ZSTD_freeDStream(zp->zds);
zp->zds = NULL;
@@ -823,7 +598,6 @@ static const struct Curl_cwtype zstd_encoding = {
};
#endif
/* Identity handler. */
static const struct Curl_cwtype identity_encoding = {
"identity",
@@ -834,7 +608,6 @@ static const struct Curl_cwtype identity_encoding = {
sizeof(struct Curl_cwriter)
};
/* supported general content decoders. */
static const struct Curl_cwtype * const general_unencoders[] = {
&identity_encoding,
@@ -898,7 +671,7 @@ void Curl_all_content_encodings(char *buf, size_t blen)
/* Deferred error dummy writer. */
static CURLcode error_do_init(struct Curl_easy *data,
struct Curl_cwriter *writer)
struct Curl_cwriter *writer)
{
(void)data;
(void)writer;
@@ -906,8 +679,8 @@ static CURLcode error_do_init(struct Curl_easy *data,
}
static CURLcode error_do_write(struct Curl_easy *data,
struct Curl_cwriter *writer, int type,
const char *buf, size_t nbytes)
struct Curl_cwriter *writer, int type,
const char *buf, size_t nbytes)
{
(void) writer;
(void) buf;
@@ -1082,5 +855,4 @@ void Curl_all_content_encodings(char *buf, size_t blen)
strcpy(buf, CONTENT_ENCODING_DEFAULT);
}
#endif /* CURL_DISABLE_HTTP */

View File

@@ -97,6 +97,26 @@ Example set of cookies:
static void strstore(char **str, const char *newstr, size_t len);
/* number of seconds in 400 days */
#define COOKIES_MAXAGE (400*24*3600)
/* Make sure cookies never expire further away in time than 400 days into the
future. (from RFC6265bis draft-19)
For the sake of easier testing, align the capped time to an even 60 second
boundary.
*/
static void cap_expires(time_t now, struct Cookie *co)
{
if((TIME_T_MAX - COOKIES_MAXAGE - 30) > now) {
timediff_t cap = now + COOKIES_MAXAGE;
if(co->expires > cap) {
cap += 30;
co->expires = (cap/60)*60;
}
}
}
static void freecookie(struct Cookie *co)
{
free(co->domain);
@@ -438,7 +458,7 @@ static bool bad_domain(const char *domain, size_t len)
fine. The prime reason for filtering out control bytes is that some HTTP
servers return 400 for requests that contain such.
*/
static int invalid_octets(const char *p)
static bool invalid_octets(const char *p)
{
/* Reject all bytes \x01 - \x1f (*except* \x09, TAB) + \x7f */
static const char badoctets[] = {
@@ -449,7 +469,7 @@ static int invalid_octets(const char *p)
size_t len;
/* scan for all the octets that are *not* in cookie-octet */
len = strcspn(p, badoctets);
return (p[len] != '\0');
return p[len] != '\0';
}
#define CERR_OK 0
@@ -469,6 +489,13 @@ static int invalid_octets(const char *p)
#define CERR_PSL 14 /* a public suffix */
#define CERR_LIVE_WINS 15
/* The maximum length we accept a date string for the 'expire' keyword. The
standard date formats are within the 30 bytes range. This adds an extra
margin just to make sure it realistically works with what is used out
there.
*/
#define MAX_DATE_LENGTH 80
static int
parse_cookie_header(struct Curl_easy *data,
struct Cookie *co,
@@ -707,16 +734,20 @@ parse_cookie_header(struct Curl_easy *data,
co->expires += now;
break;
}
cap_expires(now, co);
}
else if((nlen == 7) && strncasecompare("expires", namep, 7)) {
if(!co->expires) {
if(!co->expires && (vlen < MAX_DATE_LENGTH)) {
/*
* Let max-age have priority.
*
* If the date cannot get parsed for whatever reason, the cookie
* will be treated as a session cookie
*/
co->expires = Curl_getdate_capped(valuep);
char dbuf[MAX_DATE_LENGTH + 1];
memcpy(dbuf, valuep, vlen);
dbuf[vlen] = 0;
co->expires = Curl_getdate_capped(dbuf);
/*
* Session cookies have expires set to 0 so if we get that back
@@ -727,6 +758,7 @@ parse_cookie_header(struct Curl_easy *data,
co->expires = 1;
else if(co->expires < 0)
co->expires = 0;
cap_expires(now, co);
}
}
@@ -805,10 +837,9 @@ parse_netscape(struct Cookie *co,
* This line is NOT an HTTP header style line, we do offer support for
* reading the odd netscape cookies-file format here
*/
char *ptr;
char *firstptr;
char *tok_buf = NULL;
const char *ptr, *next;
int fields;
size_t len;
/*
* In 2008, Internet Explorer introduced HTTP-only cookies to prevent XSS
@@ -825,29 +856,22 @@ parse_netscape(struct Cookie *co,
/* do not even try the comments */
return CERR_COMMENT;
/* strip off the possible end-of-line characters */
ptr = strchr(lineptr, '\r');
if(ptr)
*ptr = 0; /* clear it */
ptr = strchr(lineptr, '\n');
if(ptr)
*ptr = 0; /* clear it */
/* tokenize on TAB */
firstptr = Curl_strtok_r((char *)lineptr, "\t", &tok_buf);
/*
* Now loop through the fields and init the struct we already have
* allocated
*/
fields = 0;
for(ptr = firstptr; ptr;
ptr = Curl_strtok_r(NULL, "\t", &tok_buf), fields++) {
for(next = lineptr; next; fields++) {
ptr = next;
len = strcspn(ptr, "\t\r\n");
next = (ptr[len] == '\t' ? &ptr[len + 1] : NULL);
switch(fields) {
case 0:
if(ptr[0]=='.') /* skip preceding dots */
if(ptr[0]=='.') { /* skip preceding dots */
ptr++;
co->domain = strdup(ptr);
len--;
}
co->domain = Curl_memdup0(ptr, len);
if(!co->domain)
return CERR_OUT_OF_MEMORY;
break;
@@ -857,13 +881,13 @@ parse_netscape(struct Cookie *co,
* domain can access the variable. Set TRUE when the cookie says
* .domain.com and to false when the domain is complete www.domain.com
*/
co->tailmatch = !!strcasecompare(ptr, "TRUE");
co->tailmatch = !!strncasecompare(ptr, "TRUE", len);
break;
case 2:
/* The file format allows the path field to remain not filled in */
if(strcmp("TRUE", ptr) && strcmp("FALSE", ptr)) {
if(strncmp("TRUE", ptr, len) && strncmp("FALSE", ptr, len)) {
/* only if the path does not look like a boolean option! */
co->path = strdup(ptr);
co->path = Curl_memdup0(ptr, len);
if(!co->path)
return CERR_OUT_OF_MEMORY;
else {
@@ -884,7 +908,7 @@ parse_netscape(struct Cookie *co,
FALLTHROUGH();
case 3:
co->secure = FALSE;
if(strcasecompare(ptr, "TRUE")) {
if(strncasecompare(ptr, "TRUE", len)) {
if(secure || ci->running)
co->secure = TRUE;
else
@@ -892,11 +916,19 @@ parse_netscape(struct Cookie *co,
}
break;
case 4:
if(curlx_strtoofft(ptr, NULL, 10, &co->expires))
return CERR_RANGE;
{
char *endp;
const char *p;
/* make sure curlx_strtoofft won't read past the current field */
for(p = ptr; p < &ptr[len] && ISDIGIT(*p); ++p)
;
if(p == ptr || p != &ptr[len] ||
curlx_strtoofft(ptr, &endp, 10, &co->expires) || endp != &ptr[len])
return CERR_RANGE;
}
break;
case 5:
co->name = strdup(ptr);
co->name = Curl_memdup0(ptr, len);
if(!co->name)
return CERR_OUT_OF_MEMORY;
else {
@@ -908,7 +940,7 @@ parse_netscape(struct Cookie *co,
}
break;
case 6:
co->value = strdup(ptr);
co->value = Curl_memdup0(ptr, len);
if(!co->value)
return CERR_OUT_OF_MEMORY;
break;
@@ -1303,14 +1335,14 @@ static int cookie_sort(const void *p1, const void *p2)
l2 = c2->path ? strlen(c2->path) : 0;
if(l1 != l2)
return (l2 > l1) ? 1 : -1 ; /* avoid size_t <=> int conversions */
return (l2 > l1) ? 1 : -1; /* avoid size_t <=> int conversions */
/* 2 - compare cookie domain lengths */
l1 = c1->domain ? strlen(c1->domain) : 0;
l2 = c2->domain ? strlen(c2->domain) : 0;
if(l1 != l2)
return (l2 > l1) ? 1 : -1 ; /* avoid size_t <=> int conversions */
return (l2 > l1) ? 1 : -1; /* avoid size_t <=> int conversions */
/* 3 - compare cookie name lengths */
l1 = c1->name ? strlen(c1->name) : 0;

View File

@@ -38,7 +38,7 @@ struct Cookie {
char *spath; /* sanitized cookie path */
char *domain; /* domain = <this> */
curl_off_t expires; /* expires = <this> */
int creationtime; /* time when the cookie was written */
unsigned int creationtime; /* time when the cookie was written */
BIT(tailmatch); /* tail-match the domain name */
BIT(secure); /* the 'secure' keyword was used */
BIT(livecookie); /* updated from a server, not a stored file */
@@ -60,10 +60,10 @@ struct CookieInfo {
/* linked lists of cookies we know of */
struct Curl_llist cookielist[COOKIE_HASH_SIZE];
curl_off_t next_expiration; /* the next time at which expiration happens */
int numcookies; /* number of cookies in the "jar" */
int lastct; /* last creation-time used in the jar */
bool running; /* state info, for cookie adding information */
bool newsession; /* new session, discard session cookies on load */
unsigned int numcookies; /* number of cookies in the "jar" */
unsigned int lastct; /* last creation-time used in the jar */
BIT(running); /* state info, for cookie adding information */
BIT(newsession); /* new session, discard session cookies on load */
};
/* The maximum sizes we accept for cookies. RFC 6265 section 6.1 says

View File

@@ -318,11 +318,7 @@ Curl_he2ai(const struct hostent *he, int port)
addr = (void *)ai->ai_addr; /* storage area for this info */
memcpy(&addr->sin_addr, curr, sizeof(struct in_addr));
#ifdef __MINGW32__
addr->sin_family = (short)(he->h_addrtype);
#else
addr->sin_family = (CURL_SA_FAMILY_T)(he->h_addrtype);
#endif
addr->sin_port = htons((unsigned short)port);
break;
@@ -331,11 +327,7 @@ Curl_he2ai(const struct hostent *he, int port)
addr6 = (void *)ai->ai_addr; /* storage area for this info */
memcpy(&addr6->sin6_addr, curr, sizeof(struct in6_addr));
#ifdef __MINGW32__
addr6->sin6_family = (short)(he->h_addrtype);
#else
addr6->sin6_family = (CURL_SA_FAMILY_T)(he->h_addrtype);
#endif
addr6->sin6_port = htons((unsigned short)port);
break;
#endif

View File

@@ -565,9 +565,6 @@
/* Define to 1 if you have the <sys/filio.h> header file. */
#cmakedefine HAVE_SYS_FILIO_H 1
/* Define to 1 if you have the <sys/wait.h> header file. */
#cmakedefine HAVE_SYS_WAIT_H 1
/* Define to 1 if you have the <sys/ioctl.h> header file. */
#cmakedefine HAVE_SYS_IOCTL_H 1
@@ -625,8 +622,8 @@
/* Define this symbol if your OS supports changing the contents of argv */
#cmakedefine HAVE_WRITABLE_ARGV 1
/* Define to 1 if you need the malloc.h header file even with stdlib.h */
#cmakedefine NEED_MALLOC_H 1
/* Define this if time_t is unsigned */
#cmakedefine HAVE_TIME_T_UNSIGNED 1
/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */
#cmakedefine NEED_REENTRANT 1
@@ -634,24 +631,6 @@
/* cpu-machine-OS */
#cmakedefine CURL_OS ${CURL_OS}
/* Name of package */
#cmakedefine PACKAGE ${PACKAGE}
/* Define to the address where bug reports for this package should be sent. */
#cmakedefine PACKAGE_BUGREPORT ${PACKAGE_BUGREPORT}
/* Define to the full name of this package. */
#cmakedefine PACKAGE_NAME ${PACKAGE_NAME}
/* Define to the full name and version of this package. */
#cmakedefine PACKAGE_STRING ${PACKAGE_STRING}
/* Define to the one symbol short name of this package. */
#cmakedefine PACKAGE_TARNAME ${PACKAGE_TARNAME}
/* Define to the version of this package. */
#cmakedefine PACKAGE_VERSION ${PACKAGE_VERSION}
/*
Note: SIZEOF_* variables are fetched with CMake through check_type_size().
As per CMake documentation on CheckTypeSize, C preprocessor code is
@@ -703,6 +682,9 @@ ${SIZEOF_TIME_T_CODE}
/* if Secure Transport is enabled */
#cmakedefine USE_SECTRANSP 1
/* if SSL session export support is available */
#cmakedefine USE_SSLS_EXPORT 1
/* if mbedTLS is enabled */
#cmakedefine USE_MBEDTLS 1
@@ -742,6 +724,9 @@ ${SIZEOF_TIME_T_CODE}
/* if OpenSSL is in use */
#cmakedefine USE_OPENSSL 1
/* if AmiSSL is in use */
#cmakedefine USE_AMISSL 1
/* if librtmp/rtmpdump is in use */
#cmakedefine USE_LIBRTMP 1
@@ -791,12 +776,12 @@ ${SIZEOF_TIME_T_CODE}
/* to enable Windows SSL */
#cmakedefine USE_SCHANNEL 1
/* if Watt-32 is in use */
#cmakedefine USE_WATT32 1
/* enable multiple SSL backends */
#cmakedefine CURL_WITH_MULTI_SSL 1
/* Version number of package */
#cmakedefine VERSION ${VERSION}
/* Number of bits in a file offset, on hosts where this is settable. */
#cmakedefine _FILE_OFFSET_BITS ${_FILE_OFFSET_BITS}
@@ -841,3 +826,9 @@ ${SIZEOF_TIME_T_CODE}
/* if ECH support is available */
#cmakedefine USE_ECH 1
/* Define to 1 if you have the wolfSSL_CTX_GenerateEchConfig function. */
#cmakedefine HAVE_WOLFSSL_CTX_GENERATEECHCONFIG
/* Define to 1 if you have the SSL_set1_ech_config_list function. */
#cmakedefine HAVE_SSL_SET1_ECH_CONFIG_LIST

View File

@@ -46,6 +46,6 @@
#define ISURLPUNTCS(x) (((x) == '-') || ((x) == '.') || ((x) == '_') || \
((x) == '~'))
#define ISUNRESERVED(x) (ISALNUM(x) || ISURLPUNTCS(x))
#define ISNEWLINE(x) (((x) == '\n') || (x) == '\r')
#endif /* HEADER_CURL_CTYPE_H */

View File

@@ -28,7 +28,9 @@
!defined(CURL_DISABLE_HSTS) || !defined(CURL_DISABLE_NETRC)
#include "curl_get_line.h"
#ifdef BUILDING_LIBCURL
#include "curl_memory.h"
#endif
/* The last #include file should be: */
#include "memdebug.h"

View File

@@ -26,6 +26,12 @@
#include "dynbuf.h"
#ifndef BUILDING_LIBCURL
/* this renames functions so that the tool code can use the same code
without getting symbol collisions */
#define Curl_get_line(a,b) curlx_get_line(a,b)
#endif
/* Curl_get_line() returns complete lines that end with a newline. */
int Curl_get_line(struct dynbuf *buf, FILE *input);

View File

@@ -73,7 +73,11 @@ int Curl_gethostname(char * const name, GETHOSTNAME_TYPE_ARG2 namelen)
#else /* DEBUGBUILD */
name[0] = '\0';
#ifdef __AMIGA__
err = gethostname((unsigned char *)name, namelen);
#else
err = gethostname(name, namelen);
#endif
#endif

View File

@@ -40,6 +40,11 @@
#define CURL_ALIGN8
#endif
#if defined(__GNUC__) && defined(__APPLE__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
gss_OID_desc Curl_spnego_mech_oid CURL_ALIGN8 = {
6, (char *)"\x2b\x06\x01\x05\x05\x02"
};
@@ -149,4 +154,8 @@ void Curl_gss_log_error(struct Curl_easy *data, const char *prefix,
#endif
}
#if defined(__GNUC__) && defined(__APPLE__)
#pragma GCC diagnostic pop
#endif
#endif /* HAVE_GSSAPI */

View File

@@ -24,9 +24,9 @@
*
***************************************************************************/
#if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI)) \
|| !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH) \
|| defined(USE_LIBSSH2)
#if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI)) || \
!defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH) || \
defined(USE_SSL)
#include <curl/curl.h>

View File

@@ -32,7 +32,7 @@
#include "curl_setup.h"
#if defined(_WIN32)
#ifdef _WIN32
#include "curl_multibyte.h"
@@ -84,16 +84,170 @@ char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w)
return str_utf8;
}
#endif /* _WIN32 */
/* declare GetFullPathNameW for mingw-w64 UWP builds targeting old windows */
#if defined(CURL_WINDOWS_UWP) && defined(__MINGW32__) && \
(_WIN32_WINNT < _WIN32_WINNT_WIN10)
WINBASEAPI DWORD WINAPI GetFullPathNameW(LPCWSTR, DWORD, LPWSTR, LPWSTR *);
#endif
#if defined(USE_WIN32_LARGE_FILES) || defined(USE_WIN32_SMALL_FILES)
/* Fix excessive paths (paths that exceed MAX_PATH length of 260).
*
* This is a helper function to fix paths that would exceed the MAX_PATH
* limitation check done by Windows APIs. It does so by normalizing the passed
* in filename or path 'in' to its full canonical path, and if that path is
* longer than MAX_PATH then setting 'out' to "\\?\" prefix + that full path.
*
* For example 'in' filename255chars in current directory C:\foo\bar is
* fixed as \\?\C:\foo\bar\filename255chars for 'out' which will tell Windows
* it is ok to access that filename even though the actual full path is longer
* than 260 chars.
*
* For non-Unicode builds this function may fail sometimes because only the
* Unicode versions of some Windows API functions can access paths longer than
* MAX_PATH, for example GetFullPathNameW which is used in this function. When
* the full path is then converted from Unicode to multibyte that fails if any
* directories in the path contain characters not in the current codepage.
*/
static bool fix_excessive_path(const TCHAR *in, TCHAR **out)
{
size_t needed, count;
const wchar_t *in_w;
wchar_t *fbuf = NULL;
/* MS documented "approximate" limit for the maximum path length */
const size_t max_path_len = 32767;
#ifndef _UNICODE
wchar_t *ibuf = NULL;
char *obuf = NULL;
#endif
*out = NULL;
/* skip paths already normalized */
if(!_tcsncmp(in, _T("\\\\?\\"), 4))
goto cleanup;
#ifndef _UNICODE
/* convert multibyte input to unicode */
needed = mbstowcs(NULL, in, 0);
if(needed == (size_t)-1 || needed >= max_path_len)
goto cleanup;
++needed; /* for NUL */
ibuf = malloc(needed * sizeof(wchar_t));
if(!ibuf)
goto cleanup;
count = mbstowcs(ibuf, in, needed);
if(count == (size_t)-1 || count >= needed)
goto cleanup;
in_w = ibuf;
#else
in_w = in;
#endif
/* GetFullPathNameW returns the normalized full path in unicode. It converts
forward slashes to backslashes, processes .. to remove directory segments,
etc. Unlike GetFullPathNameA it can process paths that exceed MAX_PATH. */
needed = (size_t)GetFullPathNameW(in_w, 0, NULL, NULL);
if(!needed || needed > max_path_len)
goto cleanup;
/* skip paths that are not excessive and do not need modification */
if(needed <= MAX_PATH)
goto cleanup;
fbuf = malloc(needed * sizeof(wchar_t));
if(!fbuf)
goto cleanup;
count = (size_t)GetFullPathNameW(in_w, (DWORD)needed, fbuf, NULL);
if(!count || count >= needed)
goto cleanup;
/* prepend \\?\ or \\?\UNC\ to the excessively long path.
*
* c:\longpath ---> \\?\c:\longpath
* \\.\c:\longpath ---> \\?\c:\longpath
* \\?\c:\longpath ---> \\?\c:\longpath (unchanged)
* \\server\c$\longpath ---> \\?\UNC\server\c$\longpath
*
* https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats
*/
if(!wcsncmp(fbuf, L"\\\\?\\", 4))
; /* do nothing */
else if(!wcsncmp(fbuf, L"\\\\.\\", 4))
fbuf[2] = '?';
else if(!wcsncmp(fbuf, L"\\\\.", 3) || !wcsncmp(fbuf, L"\\\\?", 3)) {
/* Unexpected, not UNC. The formatting doc doesn't allow this AFAICT. */
goto cleanup;
}
else {
wchar_t *temp;
if(!wcsncmp(fbuf, L"\\\\", 2)) {
/* "\\?\UNC\" + full path without "\\" + null */
needed = 8 + (count - 2) + 1;
if(needed > max_path_len)
goto cleanup;
temp = malloc(needed * sizeof(wchar_t));
if(!temp)
goto cleanup;
wcsncpy(temp, L"\\\\?\\UNC\\", 8);
wcscpy(temp + 8, fbuf + 2);
}
else {
/* "\\?\" + full path + null */
needed = 4 + count + 1;
if(needed > max_path_len)
goto cleanup;
temp = malloc(needed * sizeof(wchar_t));
if(!temp)
goto cleanup;
wcsncpy(temp, L"\\\\?\\", 4);
wcscpy(temp + 4, fbuf);
}
free(fbuf);
fbuf = temp;
}
#ifndef _UNICODE
/* convert unicode full path to multibyte output */
needed = wcstombs(NULL, fbuf, 0);
if(needed == (size_t)-1 || needed >= max_path_len)
goto cleanup;
++needed; /* for NUL */
obuf = malloc(needed);
if(!obuf)
goto cleanup;
count = wcstombs(obuf, fbuf, needed);
if(count == (size_t)-1 || count >= needed)
goto cleanup;
*out = obuf;
obuf = NULL;
#else
*out = fbuf;
fbuf = NULL;
#endif
cleanup:
free(fbuf);
#ifndef _UNICODE
free(ibuf);
free(obuf);
#endif
return *out ? true : false;
}
int curlx_win32_open(const char *filename, int oflag, ...)
{
int pmode = 0;
int result = -1;
TCHAR *fixed = NULL;
const TCHAR *target = NULL;
#ifdef _UNICODE
int result = -1;
wchar_t *filename_w = curlx_convert_UTF8_to_wchar(filename);
#endif
@@ -105,58 +259,95 @@ int curlx_win32_open(const char *filename, int oflag, ...)
#ifdef _UNICODE
if(filename_w) {
result = _wopen(filename_w, oflag, pmode);
if(fix_excessive_path(filename_w, &fixed))
target = fixed;
else
target = filename_w;
result = _wopen(target, oflag, pmode);
curlx_unicodefree(filename_w);
}
else
errno = EINVAL;
return result;
#else
return (_open)(filename, oflag, pmode);
if(fix_excessive_path(filename, &fixed))
target = fixed;
else
target = filename;
result = (_open)(target, oflag, pmode);
#endif
free(fixed);
return result;
}
FILE *curlx_win32_fopen(const char *filename, const char *mode)
{
#ifdef _UNICODE
FILE *result = NULL;
TCHAR *fixed = NULL;
const TCHAR *target = NULL;
#ifdef _UNICODE
wchar_t *filename_w = curlx_convert_UTF8_to_wchar(filename);
wchar_t *mode_w = curlx_convert_UTF8_to_wchar(mode);
if(filename_w && mode_w)
result = _wfopen(filename_w, mode_w);
if(filename_w && mode_w) {
if(fix_excessive_path(filename_w, &fixed))
target = fixed;
else
target = filename_w;
result = _wfopen(target, mode_w);
}
else
errno = EINVAL;
curlx_unicodefree(filename_w);
curlx_unicodefree(mode_w);
return result;
#else
return (fopen)(filename, mode);
if(fix_excessive_path(filename, &fixed))
target = fixed;
else
target = filename;
result = (fopen)(target, mode);
#endif
free(fixed);
return result;
}
int curlx_win32_stat(const char *path, struct_stat *buffer)
{
#ifdef _UNICODE
int result = -1;
TCHAR *fixed = NULL;
const TCHAR *target = NULL;
#ifdef _UNICODE
wchar_t *path_w = curlx_convert_UTF8_to_wchar(path);
if(path_w) {
#if defined(USE_WIN32_SMALL_FILES)
result = _wstat(path_w, buffer);
if(fix_excessive_path(path_w, &fixed))
target = fixed;
else
target = path_w;
#ifndef USE_WIN32_LARGE_FILES
result = _wstat(target, buffer);
#else
result = _wstati64(path_w, buffer);
result = _wstati64(target, buffer);
#endif
curlx_unicodefree(path_w);
}
else
errno = EINVAL;
#else
if(fix_excessive_path(path, &fixed))
target = fixed;
else
target = path;
#ifndef USE_WIN32_LARGE_FILES
result = _stat(target, buffer);
#else
result = _stati64(target, buffer);
#endif
#endif
free(fixed);
return result;
#else
#if defined(USE_WIN32_SMALL_FILES)
return _stat(path, buffer);
#else
return _stati64(path, buffer);
#endif
#endif
}
#endif /* USE_WIN32_LARGE_FILES || USE_WIN32_SMALL_FILES */
#endif /* _WIN32 */

View File

@@ -85,6 +85,7 @@ const struct Curl_handler Curl_handler_rtmp = {
ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
ZERO_NULL, /* follow */
PORT_RTMP, /* defport */
CURLPROTO_RTMP, /* protocol */
CURLPROTO_RTMP, /* family */
@@ -109,6 +110,7 @@ const struct Curl_handler Curl_handler_rtmpt = {
ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
ZERO_NULL, /* follow */
PORT_RTMPT, /* defport */
CURLPROTO_RTMPT, /* protocol */
CURLPROTO_RTMPT, /* family */
@@ -133,6 +135,7 @@ const struct Curl_handler Curl_handler_rtmpe = {
ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
ZERO_NULL, /* follow */
PORT_RTMP, /* defport */
CURLPROTO_RTMPE, /* protocol */
CURLPROTO_RTMPE, /* family */
@@ -157,6 +160,7 @@ const struct Curl_handler Curl_handler_rtmpte = {
ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
ZERO_NULL, /* follow */
PORT_RTMPT, /* defport */
CURLPROTO_RTMPTE, /* protocol */
CURLPROTO_RTMPTE, /* family */
@@ -181,6 +185,7 @@ const struct Curl_handler Curl_handler_rtmps = {
ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
ZERO_NULL, /* follow */
PORT_RTMPS, /* defport */
CURLPROTO_RTMPS, /* protocol */
CURLPROTO_RTMP, /* family */
@@ -205,6 +210,7 @@ const struct Curl_handler Curl_handler_rtmpts = {
ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
ZERO_NULL, /* follow */
PORT_RTMPS, /* defport */
CURLPROTO_RTMPTS, /* protocol */
CURLPROTO_RTMPT, /* family */

View File

@@ -31,13 +31,6 @@
/* Tell "curl/curl.h" not to include "curl/mprintf.h" */
#define CURL_SKIP_INCLUDE_MPRINTF
/* FIXME: Delete this once the warnings have been fixed. */
#if !defined(CURL_WARN_SIGN_CONVERSION)
#if defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic ignored "-Wsign-conversion"
#endif
#endif
/* Set default _WIN32_WINNT */
#ifdef __MINGW32__
#include <_mingw.h>
@@ -85,13 +78,17 @@
#endif
#endif
/*
* Disable Visual Studio warnings:
* 4127 "conditional expression is constant"
*/
#ifdef _MSC_VER
/* Disable Visual Studio warnings: 4127 "conditional expression is constant" */
#pragma warning(disable:4127)
/* Avoid VS2005 and upper complaining about portable C functions. */
#ifndef _CRT_NONSTDC_NO_DEPRECATE
#define _CRT_NONSTDC_NO_DEPRECATE /* for strdup(), write(), etc. */
#endif
#ifndef _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_DEPRECATE /* for fopen(), getenv(), etc. */
#endif
#endif /* _MSC_VER */
#ifdef _WIN32
/*
@@ -100,26 +97,26 @@
* Make sure to define this macro before including any Windows headers.
*/
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# ifndef NOGDI
# define NOGDI
# define NOGDI
# endif
/* Detect Windows App environment which has a restricted access
* to the Win32 APIs. */
# if (defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0602)) || \
defined(WINAPI_FAMILY)
# include <winapifamily.h>
# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \
!WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
# define CURL_WINDOWS_UWP
# if (defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0602)) || \
defined(WINAPI_FAMILY)
# include <winapifamily.h>
# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \
!WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
# define CURL_WINDOWS_UWP
# endif
# endif
# endif
#endif
/* Compatibility */
#if defined(ENABLE_IPV6)
# define USE_IPV6 1
#ifdef ENABLE_IPV6
#define USE_IPV6 1
#endif
/*
@@ -133,12 +130,8 @@
#else /* HAVE_CONFIG_H */
#ifdef _WIN32_WCE
# include "config-win32ce.h"
#else
# ifdef _WIN32
# include "config-win32.h"
# endif
#ifdef _WIN32
# include "config-win32.h"
#endif
#ifdef macintosh
@@ -149,10 +142,6 @@
# include "config-riscos.h"
#endif
#ifdef __AMIGA__
# include "config-amigaos.h"
#endif
#ifdef __OS400__
# include "config-os400.h"
#endif
@@ -161,10 +150,6 @@
# include "config-plan9.h"
#endif
#ifdef MSDOS
# include "config-dos.h"
#endif
#endif /* HAVE_CONFIG_H */
/* ================================================================ */
@@ -183,7 +168,7 @@
#ifdef NEED_THREAD_SAFE
# ifndef _THREAD_SAFE
# define _THREAD_SAFE
# define _THREAD_SAFE
# endif
#endif
@@ -195,14 +180,14 @@
#ifdef NEED_REENTRANT
# ifndef _REENTRANT
# define _REENTRANT
# define _REENTRANT
# endif
#endif
/* Solaris needs this to get a POSIX-conformant getpwuid_r */
#if defined(sun) || defined(__sun)
# ifndef _POSIX_PTHREAD_SEMANTICS
# define _POSIX_PTHREAD_SEMANTICS 1
# define _POSIX_PTHREAD_SEMANTICS 1
# endif
#endif
@@ -290,14 +275,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. */
@@ -393,17 +370,23 @@
# endif
#endif
#ifdef USE_ARES
# ifndef CARES_NO_DEPRECATED
# define CARES_NO_DEPRECATED /* for ares_getsock() */
# endif
# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && defined(_WIN32)
# define CARES_STATICLIB /* define it before including ares.h */
# endif
#endif
#ifdef USE_LWIPSOCK
# include <lwip/init.h>
# include <lwip/sockets.h>
# include <lwip/netdb.h>
#endif
#ifdef HAVE_EXTRA_STRICMP_H
#ifdef macintosh
# include <extra/stricmp.h>
#endif
#ifdef HAVE_EXTRA_STRDUP_H
# include <extra/strdup.h>
#endif
@@ -456,9 +439,9 @@
#include <assert.h>
#ifdef __TANDEM /* for ns*-tandem-nsk systems */
# if ! defined __LP64
# include <floss.h> /* FLOSS is only used for 32-bit builds. */
# endif
# if ! defined __LP64
# include <floss.h> /* FLOSS is only used for 32-bit builds. */
# endif
#endif
#ifndef STDC_HEADERS /* no standard C headers! */
@@ -494,11 +477,19 @@
FILE *curlx_win32_fopen(const char *filename, const char *mode);
#endif
#ifdef __DJGPP__
/* Requires DJGPP 2.04 */
# include <unistd.h>
# undef lseek
# define lseek(fdes,offset,whence) llseek(fdes, offset, whence)
# define LSEEK_ERROR (offset_t)-1
#endif
/*
* Small file (<2Gb) support using Win32 functions.
*/
#ifdef USE_WIN32_SMALL_FILES
#if defined(_WIN32) && !defined(USE_WIN32_LARGE_FILES)
# include <io.h>
# include <sys/types.h>
# include <sys/stat.h>
@@ -518,11 +509,11 @@
#endif
#ifndef struct_stat
# define struct_stat struct stat
#define struct_stat struct stat
#endif
#ifndef LSEEK_ERROR
# define LSEEK_ERROR (off_t)-1
#define LSEEK_ERROR (off_t)-1
#endif
#ifndef SIZEOF_TIME_T
@@ -593,8 +584,8 @@
# endif
# define CURL_UINT64_SUFFIX CURL_SUFFIX_CURL_OFF_TU
# define CURL_UINT64_C(val) CURL_CONC_MACROS(val,CURL_UINT64_SUFFIX)
# define FMT_PRId64 CURL_FORMAT_CURL_OFF_T
# define FMT_PRIu64 CURL_FORMAT_CURL_OFF_TU
# define FMT_PRId64 CURL_FORMAT_CURL_OFF_T
# define FMT_PRIu64 CURL_FORMAT_CURL_OFF_TU
#endif
#define FMT_OFF_T CURL_FORMAT_CURL_OFF_T
@@ -693,9 +684,9 @@
/*
* MSVC threads support requires a multi-threaded runtime library.
* _beginthreadex() is not available in single-threaded ones.
* Single-threaded option was last available in VS2005: _MSC_VER <= 1400
*/
#if defined(_MSC_VER) && !defined(_MT)
#if defined(_MSC_VER) && !defined(_MT) /* available in _MSC_VER <= 1400 */
# undef USE_THREADS_POSIX
# undef USE_THREADS_WIN32
#endif
@@ -713,15 +704,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
@@ -738,14 +729,23 @@
#error "libidn2 cannot be enabled with WinIDN or AppleIDN, choose one."
#endif
#define LIBIDN_REQUIRED_VERSION "0.4.1"
#if defined(USE_GNUTLS) || defined(USE_OPENSSL) || defined(USE_MBEDTLS) || \
defined(USE_WOLFSSL) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \
defined(USE_BEARSSL) || defined(USE_RUSTLS)
#define USE_SSL /* SSL support has been enabled */
#endif
#if defined(USE_OPENSSL) && defined(USE_WOLFSSL)
# include <wolfssl/version.h>
# if LIBWOLFSSL_VERSION_HEX >= 0x05007006
# ifndef OPENSSL_COEXIST
# define OPENSSL_COEXIST
# endif
# else
# error "OpenSSL can only coexist with wolfSSL v5.7.6 or upper"
# endif
#endif
#if defined(USE_WOLFSSL) && defined(USE_GNUTLS)
/* Avoid defining unprefixed wolfSSL SHA macros colliding with nettle ones */
#define NO_OLD_WC_NAMES
@@ -776,10 +776,6 @@
# endif
#endif
#ifdef CURL_WANTS_CA_BUNDLE_ENV
#error "No longer supported. Set CURLOPT_CAINFO at runtime instead."
#endif
#if defined(USE_LIBSSH2) || defined(USE_LIBSSH) || defined(USE_WOLFSSH)
#define USE_SSH
#endif
@@ -812,7 +808,7 @@
#if (defined(__GNUC__) && (__GNUC__ >= 3)) || defined(__clang__) || \
defined(__IAR_SYSTEMS_ICC__)
# define CURL_NORETURN __attribute__((__noreturn__))
#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
#elif defined(_MSC_VER)
# define CURL_NORETURN __declspec(noreturn)
#else
# define CURL_NORETURN
@@ -843,7 +839,7 @@
*/
#ifndef Curl_nop_stmt
# define Curl_nop_stmt do { } while(0)
#define Curl_nop_stmt do { } while(0)
#endif
/*
@@ -882,6 +878,14 @@
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
/* Since O_BINARY is used in bitmasks, setting it to zero makes it usable in
source code but yet it does not ruin anything */
#ifdef O_BINARY
#define CURL_O_BINARY O_BINARY
#else
#define CURL_O_BINARY 0
#endif
/* In Windows the default file mode is text but an application can override it.
Therefore we specify it explicitly. https://github.com/curl/curl/pull/258
*/
@@ -911,6 +915,8 @@ endings either CRLF or LF so 't' is appropriate.
# define CURL_SA_FAMILY_T sa_family_t
# elif defined(HAVE_ADDRESS_FAMILY)
# define CURL_SA_FAMILY_T ADDRESS_FAMILY
# elif defined(__AMIGA__)
# define CURL_SA_FAMILY_T unsigned char
# else
/* use a sensible default */
# define CURL_SA_FAMILY_T unsigned short
@@ -927,8 +933,9 @@ endings either CRLF or LF so 't' is appropriate.
as their argument */
#define STRCONST(x) x,sizeof(x)-1
/* Some versions of the Android SDK is missing the declaration */
#if defined(HAVE_GETPWUID_R) && defined(HAVE_DECL_GETPWUID_R_MISSING)
/* Some versions of the Android NDK is missing the declaration */
#if defined(HAVE_GETPWUID_R) && \
defined(__ANDROID_API__) && (__ANDROID_API__ < 21)
struct passwd;
int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf,
size_t buflen, struct passwd **result);
@@ -940,8 +947,7 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf,
#define UNITTEST static
#endif
/* Hyper supports HTTP2 also, but Curl's integration with Hyper does not */
#if defined(USE_NGHTTP2)
#ifdef USE_NGHTTP2
#define USE_HTTP2
#endif
@@ -950,7 +956,7 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf,
defined(USE_QUICHE) || defined(USE_MSH3)
#ifdef CURL_WITH_MULTI_SSL
#error "Multi-SSL combined with QUIC is not supported"
#error "MultiSSL combined with QUIC is not supported"
#endif
#define USE_HTTP3
@@ -970,7 +976,7 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf,
# define UNIX_PATH_MAX 108
/* !checksrc! disable TYPEDEFSTRUCT 1 */
typedef struct sockaddr_un {
ADDRESS_FAMILY sun_family;
CURL_SA_FAMILY_T sun_family;
char sun_path[UNIX_PATH_MAX];
} SOCKADDR_UN, *PSOCKADDR_UN;
# define WIN32_SOCKADDR_UN
@@ -983,26 +989,26 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf,
#define OPENSSL_SUPPRESS_DEPRECATED
#endif
#if defined(inline)
/* 'inline' is defined as macro and assumed to be correct */
/* No need for 'inline' replacement */
#if defined(CURL_INLINE)
/* 'CURL_INLINE' defined, use as-is */
#elif defined(inline)
# define CURL_INLINE inline /* 'inline' defined, assumed correct */
#elif defined(__cplusplus)
/* The code is compiled with C++ compiler.
C++ always supports 'inline'. */
/* No need for 'inline' replacement */
/* The code is compiled with C++ compiler.
C++ always supports 'inline'. */
# define CURL_INLINE inline /* 'inline' keyword supported */
#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901
/* C99 (and later) supports 'inline' keyword */
/* No need for 'inline' replacement */
/* C99 (and later) supports 'inline' keyword */
# define CURL_INLINE inline /* 'inline' keyword supported */
#elif defined(__GNUC__) && __GNUC__ >= 3
/* GCC supports '__inline__' as an extension */
# define inline __inline__
#elif defined(_MSC_VER) && _MSC_VER >= 1400
/* MSC supports '__inline' from VS 2005 (or even earlier) */
# define inline __inline
/* GCC supports '__inline__' as an extension */
# define CURL_INLINE __inline__
#elif defined(_MSC_VER)
# define CURL_INLINE __inline
#else
/* Probably 'inline' is not supported by compiler.
Define to the empty string to be on the safe side. */
# define inline /* empty */
/* Probably 'inline' is not supported by compiler.
Define to the empty string to be on the safe side. */
# define CURL_INLINE /* empty */
#endif
#endif /* HEADER_CURL_SETUP_H */

View File

@@ -24,7 +24,6 @@
*
***************************************************************************/
/*
* Inclusion of common header files.
*/
@@ -40,14 +39,6 @@
#include <sys/types.h>
#endif
#ifdef NEED_MALLOC_H
#include <malloc.h>
#endif
#ifdef NEED_MEMORY_H
#include <memory.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
@@ -56,8 +47,11 @@
#include <sys/time.h>
#endif
#ifdef _WIN32
#ifdef HAVE_IO_H
#include <io.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
@@ -111,8 +105,8 @@
#ifndef HAVE_STRUCT_TIMEVAL
struct timeval {
long tv_sec;
long tv_usec;
long tv_sec;
long tv_usec;
};
#endif
@@ -195,7 +189,7 @@ struct timeval {
# define sclose(x) closesocket((x))
#elif defined(HAVE_CLOSESOCKET_CAMEL)
# define sclose(x) CloseSocket((x))
#elif defined(HAVE_CLOSE_S)
#elif defined(MSDOS) /* Watt-32 */
# define sclose(x) close_s((x))
#elif defined(USE_LWIPSOCK)
# define sclose(x) lwip_close((x))
@@ -233,8 +227,8 @@ struct timeval {
#ifndef HAVE_BOOL_T
typedef enum {
bool_false = 0,
bool_true = 1
bool_false = 0,
bool_true = 1
} bool;
/*
@@ -397,7 +391,7 @@ typedef unsigned int bit;
#ifdef __VMS
#define argv_item_t __char_ptr32
#elif defined(_UNICODE)
#define argv_item_t wchar_t *
#define argv_item_t wchar_t *
#else
#define argv_item_t char *
#endif

View File

@@ -26,7 +26,7 @@
***************************************************************************/
#if !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH) \
|| defined(USE_LIBSSH2)
|| defined(USE_LIBSSH2) || defined(USE_SSL)
#include <curl/curl.h>
#include "curl_hmac.h"

View File

@@ -283,28 +283,26 @@ Curl_sha512_256_finish(unsigned char *digest,
#ifdef __GNUC__
# if defined(__has_attribute) && defined(__STDC_VERSION__)
# if __has_attribute(always_inline) && __STDC_VERSION__ >= 199901
# define MHDX_INLINE inline __attribute__((always_inline))
# define CURL_FORCEINLINE CURL_INLINE __attribute__((always_inline))
# endif
# endif
#endif
#if !defined(MHDX_INLINE) && \
#if !defined(CURL_FORCEINLINE) && \
defined(_MSC_VER) && !defined(__GNUC__) && !defined(__clang__)
# if _MSC_VER >= 1400
# define MHDX_INLINE __forceinline
# endif
# define CURL_FORCEINLINE __forceinline
#endif
#if !defined(MHDX_INLINE)
/* Assume that 'inline' keyword works or the
#if !defined(CURL_FORCEINLINE)
/* Assume that 'CURL_INLINE' keyword works or the
* macro was already defined correctly. */
# define MHDX_INLINE inline
# define CURL_FORCEINLINE CURL_INLINE
#endif
/* Bits manipulation macros and functions.
Can be moved to other headers to reuse. */
#define MHDX_GET_64BIT_BE(ptr) \
#define CURL_GET_64BIT_BE(ptr) \
( ((curl_uint64_t)(((const unsigned char*)(ptr))[0]) << 56) | \
((curl_uint64_t)(((const unsigned char*)(ptr))[1]) << 48) | \
((curl_uint64_t)(((const unsigned char*)(ptr))[2]) << 40) | \
@@ -314,7 +312,7 @@ Curl_sha512_256_finish(unsigned char *digest,
((curl_uint64_t)(((const unsigned char*)(ptr))[6]) << 8) | \
(curl_uint64_t)(((const unsigned char*)(ptr))[7]) )
#define MHDX_PUT_64BIT_BE(ptr,val) do { \
#define CURL_PUT_64BIT_BE(ptr,val) do { \
((unsigned char*)(ptr))[7]=(unsigned char)((curl_uint64_t)(val)); \
((unsigned char*)(ptr))[6]=(unsigned char)(((curl_uint64_t)(val)) >> 8); \
((unsigned char*)(ptr))[5]=(unsigned char)(((curl_uint64_t)(val)) >> 16); \
@@ -328,8 +326,8 @@ Curl_sha512_256_finish(unsigned char *digest,
/* Defined as a function. The macro version may duplicate the binary code
* size as each argument is used twice, so if any calculation is used
* as an argument, the calculation could be done twice. */
static MHDX_INLINE curl_uint64_t
MHDx_rotr64(curl_uint64_t value, unsigned int bits)
static CURL_FORCEINLINE curl_uint64_t
Curl_rotr64(curl_uint64_t value, unsigned int bits)
{
bits %= 64;
if(0 == bits)
@@ -388,7 +386,7 @@ MHDx_rotr64(curl_uint64_t value, unsigned int bits)
/**
* SHA-512/256 calculation context
*/
struct mhdx_sha512_256ctx
struct Curl_sha512_256ctx
{
/**
* Intermediate hash value. The variable is properly aligned. Smart
@@ -416,7 +414,7 @@ struct mhdx_sha512_256ctx
/**
* Context type used for SHA-512/256 calculations
*/
typedef struct mhdx_sha512_256ctx Curl_sha512_256_ctx;
typedef struct Curl_sha512_256ctx Curl_sha512_256_ctx;
/**
@@ -426,9 +424,9 @@ typedef struct mhdx_sha512_256ctx Curl_sha512_256_ctx;
* @return always CURLE_OK
*/
static CURLcode
MHDx_sha512_256_init(void *context)
Curl_sha512_256_init(void *context)
{
struct mhdx_sha512_256ctx *const ctx = (struct mhdx_sha512_256ctx *) context;
struct Curl_sha512_256ctx *const ctx = (struct Curl_sha512_256ctx *)context;
/* Check whether the header and this file use the same numbers */
DEBUGASSERT(CURL_SHA512_256_DIGEST_LENGTH == CURL_SHA512_256_DIGEST_SIZE);
@@ -462,7 +460,7 @@ MHDx_sha512_256_init(void *context)
* @param data the data buffer with #CURL_SHA512_256_BLOCK_SIZE bytes block
*/
static void
MHDx_sha512_256_transform(curl_uint64_t H[SHA512_256_HASH_SIZE_WORDS],
Curl_sha512_256_transform(curl_uint64_t H[SHA512_256_HASH_SIZE_WORDS],
const void *data)
{
/* Working variables,
@@ -488,13 +486,13 @@ MHDx_sha512_256_transform(curl_uint64_t H[SHA512_256_HASH_SIZE_WORDS],
/* Four 'Sigma' macro functions.
See FIPS PUB 180-4 formulae 4.10, 4.11, 4.12, 4.13. */
#define SIG0(x) \
( MHDx_rotr64((x), 28) ^ MHDx_rotr64((x), 34) ^ MHDx_rotr64((x), 39) )
( Curl_rotr64((x), 28) ^ Curl_rotr64((x), 34) ^ Curl_rotr64((x), 39) )
#define SIG1(x) \
( MHDx_rotr64((x), 14) ^ MHDx_rotr64((x), 18) ^ MHDx_rotr64((x), 41) )
( Curl_rotr64((x), 14) ^ Curl_rotr64((x), 18) ^ Curl_rotr64((x), 41) )
#define sig0(x) \
( MHDx_rotr64((x), 1) ^ MHDx_rotr64((x), 8) ^ ((x) >> 7) )
( Curl_rotr64((x), 1) ^ Curl_rotr64((x), 8) ^ ((x) >> 7) )
#define sig1(x) \
( MHDx_rotr64((x), 19) ^ MHDx_rotr64((x), 61) ^ ((x) >> 6) )
( Curl_rotr64((x), 19) ^ Curl_rotr64((x), 61) ^ ((x) >> 6) )
if(1) {
unsigned int t;
@@ -577,7 +575,7 @@ MHDx_sha512_256_transform(curl_uint64_t H[SHA512_256_HASH_SIZE_WORDS],
Input data must be read in big-endian bytes order,
see FIPS PUB 180-4 section 3.1.2. */
#define SHA512_GET_W_FROM_DATA(buf,t) \
MHDX_GET_64BIT_BE( \
CURL_GET_64BIT_BE( \
((const unsigned char*) (buf)) + (t) * SHA512_256_BYTES_IN_WORD)
/* During first 16 steps, before making any calculation on each step, the
@@ -628,12 +626,12 @@ MHDx_sha512_256_transform(curl_uint64_t H[SHA512_256_HASH_SIZE_WORDS],
* @return always CURLE_OK
*/
static CURLcode
MHDx_sha512_256_update(void *context,
Curl_sha512_256_update(void *context,
const unsigned char *data,
size_t length)
{
unsigned int bytes_have; /**< Number of bytes in the context buffer */
struct mhdx_sha512_256ctx *const ctx = (struct mhdx_sha512_256ctx *)context;
struct Curl_sha512_256ctx *const ctx = (struct Curl_sha512_256ctx *)context;
/* the void pointer here is required to mute Intel compiler warning */
void *const ctx_buf = ctx->buffer;
@@ -661,7 +659,7 @@ MHDx_sha512_256_update(void *context,
bytes_left);
data += bytes_left;
length -= bytes_left;
MHDx_sha512_256_transform(ctx->H, ctx->buffer);
Curl_sha512_256_transform(ctx->H, ctx->buffer);
bytes_have = 0;
}
}
@@ -669,7 +667,7 @@ MHDx_sha512_256_update(void *context,
while(CURL_SHA512_256_BLOCK_SIZE <= length) {
/* Process any full blocks of new data directly,
without copying to the buffer. */
MHDx_sha512_256_transform(ctx->H, data);
Curl_sha512_256_transform(ctx->H, data);
data += CURL_SHA512_256_BLOCK_SIZE;
length -= CURL_SHA512_256_BLOCK_SIZE;
}
@@ -705,10 +703,10 @@ MHDx_sha512_256_update(void *context,
* @return always CURLE_OK
*/
static CURLcode
MHDx_sha512_256_finish(unsigned char *digest,
Curl_sha512_256_finish(unsigned char *digest,
void *context)
{
struct mhdx_sha512_256ctx *const ctx = (struct mhdx_sha512_256ctx *)context;
struct Curl_sha512_256ctx *const ctx = (struct Curl_sha512_256ctx *)context;
curl_uint64_t num_bits; /**< Number of processed bits */
unsigned int bytes_have; /**< Number of bytes in the context buffer */
/* the void pointer here is required to mute Intel compiler warning */
@@ -742,7 +740,7 @@ MHDx_sha512_256_finish(unsigned char *digest,
memset(((unsigned char *) ctx_buf) + bytes_have, 0,
CURL_SHA512_256_BLOCK_SIZE - bytes_have);
/* Process the full block. */
MHDx_sha512_256_transform(ctx->H, ctx->buffer);
Curl_sha512_256_transform(ctx->H, ctx->buffer);
/* Start the new block. */
bytes_have = 0;
}
@@ -754,37 +752,32 @@ MHDx_sha512_256_finish(unsigned char *digest,
part of number of bits as big-endian values.
See FIPS PUB 180-4 section 5.1.2. */
/* Note: the target location is predefined and buffer is always aligned */
MHDX_PUT_64BIT_BE(((unsigned char *) ctx_buf) \
CURL_PUT_64BIT_BE(((unsigned char *) ctx_buf) \
+ CURL_SHA512_256_BLOCK_SIZE \
- SHA512_256_SIZE_OF_LEN_ADD, \
ctx->count_bits_hi);
MHDX_PUT_64BIT_BE(((unsigned char *) ctx_buf) \
CURL_PUT_64BIT_BE(((unsigned char *) ctx_buf) \
+ CURL_SHA512_256_BLOCK_SIZE \
- SHA512_256_SIZE_OF_LEN_ADD \
+ SHA512_256_BYTES_IN_WORD, \
num_bits);
/* Process the full final block. */
MHDx_sha512_256_transform(ctx->H, ctx->buffer);
Curl_sha512_256_transform(ctx->H, ctx->buffer);
/* Put in BE mode the leftmost part of the hash as the final digest.
See FIPS PUB 180-4 section 6.7. */
MHDX_PUT_64BIT_BE((digest + 0 * SHA512_256_BYTES_IN_WORD), ctx->H[0]);
MHDX_PUT_64BIT_BE((digest + 1 * SHA512_256_BYTES_IN_WORD), ctx->H[1]);
MHDX_PUT_64BIT_BE((digest + 2 * SHA512_256_BYTES_IN_WORD), ctx->H[2]);
MHDX_PUT_64BIT_BE((digest + 3 * SHA512_256_BYTES_IN_WORD), ctx->H[3]);
CURL_PUT_64BIT_BE((digest + 0 * SHA512_256_BYTES_IN_WORD), ctx->H[0]);
CURL_PUT_64BIT_BE((digest + 1 * SHA512_256_BYTES_IN_WORD), ctx->H[1]);
CURL_PUT_64BIT_BE((digest + 2 * SHA512_256_BYTES_IN_WORD), ctx->H[2]);
CURL_PUT_64BIT_BE((digest + 3 * SHA512_256_BYTES_IN_WORD), ctx->H[3]);
/* Erase potentially sensitive data. */
memset(ctx, 0, sizeof(struct mhdx_sha512_256ctx));
memset(ctx, 0, sizeof(struct Curl_sha512_256ctx));
return CURLE_OK;
}
/* Map to the local implementation */
#define Curl_sha512_256_init MHDx_sha512_256_init
#define Curl_sha512_256_update MHDx_sha512_256_update
#define Curl_sha512_256_finish MHDx_sha512_256_finish
#endif /* Local SHA-512/256 code */

View File

@@ -81,27 +81,27 @@ extern PSecurityFunctionTable Curl_pSecFn;
#endif
#ifndef SEC_I_SIGNATURE_NEEDED
# define SEC_I_SIGNATURE_NEEDED ((HRESULT)0x0009035CL)
#define SEC_I_SIGNATURE_NEEDED ((HRESULT)0x0009035CL)
#endif
#ifndef CRYPT_E_REVOKED
# define CRYPT_E_REVOKED ((HRESULT)0x80092010L)
#define CRYPT_E_REVOKED ((HRESULT)0x80092010L)
#endif
#ifndef CRYPT_E_NO_REVOCATION_DLL
# define CRYPT_E_NO_REVOCATION_DLL ((HRESULT)0x80092011L)
#define CRYPT_E_NO_REVOCATION_DLL ((HRESULT)0x80092011L)
#endif
#ifndef CRYPT_E_NO_REVOCATION_CHECK
# define CRYPT_E_NO_REVOCATION_CHECK ((HRESULT)0x80092012L)
#define CRYPT_E_NO_REVOCATION_CHECK ((HRESULT)0x80092012L)
#endif
#ifndef CRYPT_E_REVOCATION_OFFLINE
# define CRYPT_E_REVOCATION_OFFLINE ((HRESULT)0x80092013L)
#define CRYPT_E_REVOCATION_OFFLINE ((HRESULT)0x80092013L)
#endif
#ifndef CRYPT_E_NOT_IN_REVOCATION_DATABASE
# define CRYPT_E_NOT_IN_REVOCATION_DATABASE ((HRESULT)0x80092014L)
#define CRYPT_E_NOT_IN_REVOCATION_DATABASE ((HRESULT)0x80092014L)
#endif
#ifdef UNICODE

View File

@@ -239,6 +239,24 @@ void Curl_trc_smtp(struct Curl_easy *data, const char *fmt, ...)
}
#endif /* !CURL_DISABLE_SMTP */
#ifdef USE_SSL
struct curl_trc_feat Curl_trc_feat_ssls = {
"SSLS",
CURL_LOG_LVL_NONE,
};
void Curl_trc_ssls(struct Curl_easy *data, const char *fmt, ...)
{
DEBUGASSERT(!strchr(fmt, '\n'));
if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_ssls)) {
va_list ap;
va_start(ap, fmt);
trc_infof(data, &Curl_trc_feat_ssls, fmt, ap);
va_end(ap);
}
}
#endif /* USE_SSL */
#if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
struct curl_trc_feat Curl_trc_feat_ws = {
"WS",
@@ -279,6 +297,9 @@ static struct trc_feat_def trc_feats[] = {
#ifndef CURL_DISABLE_SMTP
{ &Curl_trc_feat_smtp, TRC_CT_PROTOCOL },
#endif
#ifdef USE_SSL
{ &Curl_trc_feat_ssls, TRC_CT_NETWORK },
#endif
#if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
{ &Curl_trc_feat_ws, TRC_CT_PROTOCOL },
#endif
@@ -319,7 +340,7 @@ static struct trc_cft_def trc_cfts[] = {
#ifdef USE_HTTP3
{ &Curl_cft_http3, TRC_CT_PROTOCOL },
#endif
#if !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER)
#if !defined(CURL_DISABLE_HTTP)
{ &Curl_cft_http_connect, TRC_CT_PROTOCOL },
#endif
};
@@ -427,4 +448,53 @@ CURLcode Curl_trc_init(void)
return CURLE_OK;
}
void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
{
(void)data; (void)fmt;
}
void Curl_trc_cf_infof(struct Curl_easy *data,
struct Curl_cfilter *cf,
const char *fmt, ...)
{
(void)data; (void)cf; (void)fmt;
}
struct curl_trc_feat;
void Curl_trc_write(struct Curl_easy *data, const char *fmt, ...)
{
(void)data; (void)fmt;
}
void Curl_trc_read(struct Curl_easy *data, const char *fmt, ...)
{
(void)data; (void)fmt;
}
#ifndef CURL_DISABLE_FTP
void Curl_trc_ftp(struct Curl_easy *data, const char *fmt, ...)
{
(void)data; (void)fmt;
}
#endif
#ifndef CURL_DISABLE_SMTP
void Curl_trc_smtp(struct Curl_easy *data, const char *fmt, ...)
{
(void)data; (void)fmt;
}
#endif
#if !defined(CURL_DISABLE_WEBSOCKETS) || !defined(CURL_DISABLE_HTTP)
void Curl_trc_ws(struct Curl_easy *data, const char *fmt, ...)
{
(void)data; (void)fmt;
}
#endif
void Curl_trc_ssls(struct Curl_easy *data, const char *fmt, ...)
{
(void)data;
(void)fmt;
}
#endif /* !defined(CURL_DISABLE_VERBOSE_STRINGS) */

View File

@@ -70,7 +70,45 @@ void Curl_failf(struct Curl_easy *data,
#define CURL_HAVE_C99
#endif
#ifdef CURL_HAVE_C99
/**
* Output an informational message when transfer's verbose logging is enabled.
*/
void Curl_infof(struct Curl_easy *data,
const char *fmt, ...) CURL_PRINTF(2, 3);
/**
* Output an informational message when both transfer's verbose logging
* and connection filters verbose logging are enabled.
*/
void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
const char *fmt, ...) CURL_PRINTF(3, 4);
void Curl_trc_write(struct Curl_easy *data,
const char *fmt, ...) CURL_PRINTF(2, 3);
void Curl_trc_read(struct Curl_easy *data,
const char *fmt, ...) CURL_PRINTF(2, 3);
#ifndef CURL_DISABLE_FTP
extern struct curl_trc_feat Curl_trc_feat_ftp;
void Curl_trc_ftp(struct Curl_easy *data,
const char *fmt, ...) CURL_PRINTF(2, 3);
#endif
#ifndef CURL_DISABLE_SMTP
extern struct curl_trc_feat Curl_trc_feat_smtp;
void Curl_trc_smtp(struct Curl_easy *data,
const char *fmt, ...) CURL_PRINTF(2, 3);
#endif
#ifdef USE_SSL
extern struct curl_trc_feat Curl_trc_feat_ssls;
void Curl_trc_ssls(struct Curl_easy *data,
const char *fmt, ...) CURL_PRINTF(2, 3);
#endif
#if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
extern struct curl_trc_feat Curl_trc_feat_ws;
void Curl_trc_ws(struct Curl_easy *data,
const char *fmt, ...) CURL_PRINTF(2, 3);
#endif
#if defined(CURL_HAVE_C99) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
#define infof(data, ...) \
do { if(Curl_trc_is_verbose(data)) \
Curl_infof(data, __VA_ARGS__); } while(0)
@@ -94,6 +132,11 @@ void Curl_failf(struct Curl_easy *data,
do { if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_smtp)) \
Curl_trc_smtp(data, __VA_ARGS__); } while(0)
#endif /* !CURL_DISABLE_SMTP */
#ifdef USE_SSL
#define CURL_TRC_SSLS(data, ...) \
do { if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_ssls)) \
Curl_trc_ssls(data, __VA_ARGS__); } while(0)
#endif /* USE_SSL */
#if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
#define CURL_TRC_WS(data, ...) \
do { if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_ws)) \
@@ -113,6 +156,9 @@ void Curl_failf(struct Curl_easy *data,
#ifndef CURL_DISABLE_SMTP
#define CURL_TRC_SMTP Curl_trc_smtp
#endif
#ifdef USE_SSL
#define CURL_TRC_SSLS Curl_trc_ssls
#endif
#if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
#define CURL_TRC_WS Curl_trc_ws
#endif
@@ -140,40 +186,6 @@ extern struct curl_trc_feat Curl_trc_feat_write;
(Curl_trc_is_verbose(data) && \
(ft)->log_level >= CURL_LOG_LVL_INFO)
/**
* Output an informational message when transfer's verbose logging is enabled.
*/
void Curl_infof(struct Curl_easy *data,
const char *fmt, ...) CURL_PRINTF(2, 3);
/**
* Output an informational message when both transfer's verbose logging
* and connection filters verbose logging are enabled.
*/
void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
const char *fmt, ...) CURL_PRINTF(3, 4);
void Curl_trc_write(struct Curl_easy *data,
const char *fmt, ...) CURL_PRINTF(2, 3);
void Curl_trc_read(struct Curl_easy *data,
const char *fmt, ...) CURL_PRINTF(2, 3);
#ifndef CURL_DISABLE_FTP
extern struct curl_trc_feat Curl_trc_feat_ftp;
void Curl_trc_ftp(struct Curl_easy *data,
const char *fmt, ...) CURL_PRINTF(2, 3);
#endif
#ifndef CURL_DISABLE_SMTP
extern struct curl_trc_feat Curl_trc_feat_smtp;
void Curl_trc_smtp(struct Curl_easy *data,
const char *fmt, ...) CURL_PRINTF(2, 3);
#endif
#if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
extern struct curl_trc_feat Curl_trc_feat_ws;
void Curl_trc_ws(struct Curl_easy *data,
const char *fmt, ...) CURL_PRINTF(2, 3);
#endif
#else /* defined(CURL_DISABLE_VERBOSE_STRINGS) */
/* All informational messages are not compiled in for size savings */
@@ -181,49 +193,6 @@ void Curl_trc_ws(struct Curl_easy *data,
#define Curl_trc_cf_is_verbose(x,y) (FALSE)
#define Curl_trc_ft_is_verbose(x,y) (FALSE)
static void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
{
(void)data; (void)fmt;
}
static void Curl_trc_cf_infof(struct Curl_easy *data,
struct Curl_cfilter *cf,
const char *fmt, ...)
{
(void)data; (void)cf; (void)fmt;
}
struct curl_trc_feat;
static void Curl_trc_write(struct Curl_easy *data, const char *fmt, ...)
{
(void)data; (void)fmt;
}
static void Curl_trc_read(struct Curl_easy *data, const char *fmt, ...)
{
(void)data; (void)fmt;
}
#ifndef CURL_DISABLE_FTP
static void Curl_trc_ftp(struct Curl_easy *data, const char *fmt, ...)
{
(void)data; (void)fmt;
}
#endif
#ifndef CURL_DISABLE_SMTP
static void Curl_trc_smtp(struct Curl_easy *data, const char *fmt, ...)
{
(void)data; (void)fmt;
}
#endif
#if !defined(CURL_DISABLE_WEBSOCKETS) || !defined(CURL_DISABLE_HTTP)
static void Curl_trc_ws(struct Curl_easy *data, const char *fmt, ...)
{
(void)data; (void)fmt;
}
#endif
#endif /* !defined(CURL_DISABLE_VERBOSE_STRINGS) */
#endif /* HEADER_CURL_TRC_H */

View File

@@ -93,6 +93,7 @@ const struct Curl_handler Curl_handler_dict = {
ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
ZERO_NULL, /* follow */
PORT_DICT, /* defport */
CURLPROTO_DICT, /* protocol */
CURLPROTO_DICT, /* family */

192
lib/doh.c
View File

@@ -410,12 +410,6 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
struct doh_probes *dohp;
struct connectdata *conn = data->conn;
size_t i;
#ifdef USE_HTTPSRR
/* for now, this is only used when ECH is enabled */
# ifdef USE_ECH
char *qname = NULL;
# endif
#endif
*waitp = FALSE;
(void)hostname;
(void)port;
@@ -462,34 +456,23 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
#endif
#ifdef USE_HTTPSRR
/*
* TODO: Figure out the conditions under which we want to make
* a request for an HTTPS RR when we are not doing ECH. For now,
* making this request breaks a bunch of DoH tests, e.g. test2100,
* where the additional request does not match the pre-cooked data
* files, so there is a bit of work attached to making the request
* in a non-ECH use-case. For the present, we will only make the
* request when ECH is enabled in the build and is being used for
* the curl operation.
*/
# ifdef USE_ECH
if(data->set.tls_ech & CURLECH_ENABLE
|| data->set.tls_ech & CURLECH_HARD) {
if(port == 443)
qname = strdup(hostname);
else
if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
/* Only use HTTPS RR for HTTP(S) transfers */
char *qname = NULL;
if(port != PORT_HTTPS) {
qname = aprintf("_%d._https.%s", port, hostname);
if(!qname)
goto error;
if(!qname)
goto error;
}
result = doh_run_probe(data, &dohp->probe[DOH_SLOT_HTTPS_RR],
DNS_TYPE_HTTPS, qname, data->set.str[STRING_DOH],
DNS_TYPE_HTTPS,
qname ? qname : hostname, data->set.str[STRING_DOH],
data->multi, dohp->req_hds);
Curl_safefree(qname);
free(qname);
if(result)
goto error;
dohp->pending++;
}
# endif
#endif
*waitp = TRUE; /* this never returns synchronously */
return NULL;
@@ -961,11 +944,7 @@ static CURLcode doh2ai(const struct dohentry *de, const char *hostname,
addr = (void *)ai->ai_addr; /* storage area for this info */
DEBUGASSERT(sizeof(struct in_addr) == sizeof(de->addr[i].ip.v4));
memcpy(&addr->sin_addr, &de->addr[i].ip.v4, sizeof(struct in_addr));
#ifdef __MINGW32__
addr->sin_family = (short)addrtype;
#else
addr->sin_family = addrtype;
#endif
addr->sin_family = (CURL_SA_FAMILY_T)addrtype;
addr->sin_port = htons((unsigned short)port);
break;
@@ -974,11 +953,7 @@ static CURLcode doh2ai(const struct dohentry *de, const char *hostname,
addr6 = (void *)ai->ai_addr; /* storage area for this info */
DEBUGASSERT(sizeof(struct in6_addr) == sizeof(de->addr[i].ip.v6));
memcpy(&addr6->sin6_addr, &de->addr[i].ip.v6, sizeof(struct in6_addr));
#ifdef __MINGW32__
addr6->sin6_family = (short)addrtype;
#else
addr6->sin6_family = addrtype;
#endif
addr6->sin6_family = (CURL_SA_FAMILY_T)addrtype;
addr6->sin6_port = htons((unsigned short)port);
break;
#endif
@@ -1089,62 +1064,6 @@ static CURLcode doh_decode_rdata_name(unsigned char **buf, size_t *remaining,
return CURLE_OK;
}
static CURLcode doh_decode_rdata_alpn(unsigned char *rrval, size_t len,
char **alpns)
{
/*
* spec here is as per draft-ietf-dnsop-svcb-https, section-7.1.1
* encoding is catenated list of strings each preceded by a one
* octet length
* output is comma-sep list of the strings
* implementations may or may not handle quoting of comma within
* string values, so we might see a comma within the wire format
* version of a string, in which case we will precede that by a
* backslash - same goes for a backslash character, and of course
* we need to use two backslashes in strings when we mean one;-)
*/
int remaining = (int) len;
char *oval;
size_t i;
unsigned char *cp = rrval;
struct dynbuf dval;
if(!alpns)
return CURLE_OUT_OF_MEMORY;
Curl_dyn_init(&dval, DYN_DOH_RESPONSE);
remaining = (int)len;
cp = rrval;
while(remaining > 0) {
size_t tlen = (size_t) *cp++;
/* if not 1st time, add comma */
if(remaining != (int)len && Curl_dyn_addn(&dval, ",", 1))
goto err;
remaining--;
if(tlen > (size_t)remaining)
goto err;
/* add escape char if needed, clunky but easier to read */
for(i = 0; i != tlen; i++) {
if('\\' == *cp || ',' == *cp) {
if(Curl_dyn_addn(&dval, "\\", 1))
goto err;
}
if(Curl_dyn_addn(&dval, cp++, 1))
goto err;
}
remaining -= (int)tlen;
}
/* this string is always null terminated */
oval = Curl_dyn_ptr(&dval);
if(!oval)
goto err;
*alpns = oval;
return CURLE_OK;
err:
Curl_dyn_free(&dval);
return CURLE_BAD_CONTENT_ENCODING;
}
#ifdef DEBUGBUILD
static CURLcode doh_test_alpn_escapes(void)
{
@@ -1156,24 +1075,20 @@ static CURLcode doh_test_alpn_escapes(void)
0x68, 0x32 /* value "h2" */
};
size_t example_len = sizeof(example);
char *aval = NULL;
static const char *expected = "f\\\\oo\\,bar,h2";
unsigned char aval[MAX_HTTPSRR_ALPNS] = { 0 };
static const char expected[2] = { ALPN_h2, ALPN_none };
if(doh_decode_rdata_alpn(example, example_len, &aval) != CURLE_OK)
if(Curl_httpsrr_decode_alpn(example, example_len, aval) != CURLE_OK)
return CURLE_BAD_CONTENT_ENCODING;
if(strlen(aval) != strlen(expected))
return CURLE_BAD_CONTENT_ENCODING;
if(memcmp(aval, expected, strlen(aval)))
if(memcmp(aval, expected, sizeof(expected)))
return CURLE_BAD_CONTENT_ENCODING;
return CURLE_OK;
}
#endif
static CURLcode doh_resp_decode_httpsrr(unsigned char *rrval, size_t len,
static CURLcode doh_resp_decode_httpsrr(unsigned char *cp, size_t len,
struct Curl_https_rrinfo **hrr)
{
size_t remaining = len;
unsigned char *cp = rrval;
uint16_t pcode = 0, plen = 0;
struct Curl_https_rrinfo *lhrr = NULL;
char *dnsname = NULL;
@@ -1183,73 +1098,73 @@ static CURLcode doh_resp_decode_httpsrr(unsigned char *rrval, size_t len,
if(doh_test_alpn_escapes() != CURLE_OK)
return CURLE_OUT_OF_MEMORY;
#endif
if(len <= 2)
return CURLE_BAD_FUNCTION_ARGUMENT;
lhrr = calloc(1, sizeof(struct Curl_https_rrinfo));
if(!lhrr)
return CURLE_OUT_OF_MEMORY;
lhrr->val = Curl_memdup(rrval, len);
if(!lhrr->val)
goto err;
lhrr->len = len;
if(remaining <= 2)
goto err;
lhrr->priority = (uint16_t)((cp[0] << 8) + cp[1]);
lhrr->priority = doh_get16bit(cp, 0);
cp += 2;
remaining -= (uint16_t)2;
if(doh_decode_rdata_name(&cp, &remaining, &dnsname) != CURLE_OK)
len -= 2;
if(doh_decode_rdata_name(&cp, &len, &dnsname) != CURLE_OK)
goto err;
lhrr->target = dnsname;
while(remaining >= 4) {
pcode = (uint16_t)((*cp << 8) + (*(cp + 1)));
cp += 2;
plen = (uint16_t)((*cp << 8) + (*(cp + 1)));
cp += 2;
remaining -= 4;
if(pcode == HTTPS_RR_CODE_ALPN) {
if(doh_decode_rdata_alpn(cp, plen, &lhrr->alpns) != CURLE_OK)
lhrr->port = -1; /* until set */
while(len >= 4) {
pcode = doh_get16bit(cp, 0);
plen = doh_get16bit(cp, 2);
cp += 4;
len -= 4;
switch(pcode) {
case HTTPS_RR_CODE_ALPN:
if(Curl_httpsrr_decode_alpn(cp, plen, lhrr->alpns) != CURLE_OK)
goto err;
}
if(pcode == HTTPS_RR_CODE_NO_DEF_ALPN)
break;
case HTTPS_RR_CODE_NO_DEF_ALPN:
lhrr->no_def_alpn = TRUE;
else if(pcode == HTTPS_RR_CODE_IPV4) {
break;
case HTTPS_RR_CODE_IPV4:
if(!plen)
goto err;
lhrr->ipv4hints = Curl_memdup(cp, plen);
if(!lhrr->ipv4hints)
goto err;
lhrr->ipv4hints_len = (size_t)plen;
}
else if(pcode == HTTPS_RR_CODE_ECH) {
break;
case HTTPS_RR_CODE_ECH:
if(!plen)
goto err;
lhrr->echconfiglist = Curl_memdup(cp, plen);
if(!lhrr->echconfiglist)
goto err;
lhrr->echconfiglist_len = (size_t)plen;
}
else if(pcode == HTTPS_RR_CODE_IPV6) {
break;
case HTTPS_RR_CODE_IPV6:
if(!plen)
goto err;
lhrr->ipv6hints = Curl_memdup(cp, plen);
if(!lhrr->ipv6hints)
goto err;
lhrr->ipv6hints_len = (size_t)plen;
break;
case HTTPS_RR_CODE_PORT:
lhrr->port = doh_get16bit(cp, 0);
break;
default:
break;
}
if(plen > 0 && plen <= remaining) {
if(plen > 0 && plen <= len) {
cp += plen;
remaining -= plen;
len -= plen;
}
}
DEBUGASSERT(!remaining);
DEBUGASSERT(!len);
*hrr = lhrr;
return CURLE_OK;
err:
if(lhrr) {
Curl_safefree(lhrr->target);
Curl_safefree(lhrr->echconfiglist);
Curl_safefree(lhrr->val);
Curl_safefree(lhrr->alpns);
Curl_safefree(lhrr);
}
Curl_safefree(lhrr->target);
Curl_safefree(lhrr->echconfiglist);
Curl_safefree(lhrr);
return CURLE_OUT_OF_MEMORY;
}
@@ -1260,8 +1175,9 @@ static void doh_print_httpsrr(struct Curl_easy *data,
DEBUGASSERT(hrr);
infof(data, "HTTPS RR: priority %d, target: %s",
hrr->priority, hrr->target);
if(hrr->alpns)
infof(data, "HTTPS RR: alpns %s", hrr->alpns);
if(hrr->alpns[0] != ALPN_none)
infof(data, "HTTPS RR: alpns %u %u %u %u",
hrr->alpns[0], hrr->alpns[1], hrr->alpns[2], hrr->alpns[3]);
else
infof(data, "HTTPS RR: no alpns");
if(hrr->no_def_alpn)

View File

@@ -28,6 +28,7 @@
#include "curl_addrinfo.h"
#ifdef USE_HTTPSRR
# include <stdint.h>
# include "httpsrr.h"
#endif
#ifndef CURL_DISABLE_DOH
@@ -123,19 +124,6 @@ struct dohaddr {
#ifdef USE_HTTPSRR
/*
* These are the code points for DNS wire format SvcParams as
* per draft-ietf-dnsop-svcb-https
* Not all are supported now, and even those that are may need
* more work in future to fully support the spec.
*/
#define HTTPS_RR_CODE_ALPN 0x01
#define HTTPS_RR_CODE_NO_DEF_ALPN 0x02
#define HTTPS_RR_CODE_PORT 0x03
#define HTTPS_RR_CODE_IPV4 0x04
#define HTTPS_RR_CODE_ECH 0x05
#define HTTPS_RR_CODE_IPV6 0x06
/*
* These may need escaping when found within an ALPN string
* value.

View File

@@ -244,6 +244,18 @@ char *Curl_dyn_ptr(const struct dynbuf *s)
return s->bufr;
}
char *Curl_dyn_take(struct dynbuf *s, size_t *plen)
{
char *ptr = s->bufr;
DEBUGASSERT(s);
DEBUGASSERT(s->init == DYNINIT);
*plen = s->leng;
s->bufr = NULL;
s->leng = 0;
s->allc = 0;
return ptr;
}
/*
* Returns an unsigned pointer to the buffer.
*/

View File

@@ -39,6 +39,7 @@
#define Curl_dyn_uptr(a) curlx_dyn_uptr(a)
#define Curl_dyn_len(a) curlx_dyn_len(a)
#define Curl_dyn_reset(a) curlx_dyn_reset(a)
#define Curl_dyn_take(a,b) curlx_dyn_take(a,b)
#define Curl_dyn_tail(a,b) curlx_dyn_tail(a,b)
#define Curl_dyn_setlen(a,b) curlx_dyn_setlen(a,b)
#define curlx_dynbuf dynbuf /* for the struct name */
@@ -75,6 +76,10 @@ size_t Curl_dyn_len(const struct dynbuf *s);
/* The implementation of this function exists in mprintf.c */
int Curl_dyn_vprintf(struct dynbuf *dyn, const char *format, va_list ap_save);
/* Take the buffer out of the dynbuf. Caller has ownership and
* dynbuf resets to initial state. */
char *Curl_dyn_take(struct dynbuf *s, size_t *plen);
/* Dynamic buffer max sizes */
#define DYN_DOH_RESPONSE 3000
#define DYN_DOH_CNAME 256

View File

@@ -48,6 +48,7 @@
#include <curl/curl.h>
#include "transfer.h"
#include "vtls/vtls.h"
#include "vtls/vtls_scache.h"
#include "url.h"
#include "getinfo.h"
#include "hostip.h"
@@ -761,12 +762,25 @@ static CURLcode easy_perform(struct Curl_easy *data, bool events)
return CURLE_FAILED_INIT;
}
/* if the handle has a connection still attached (it is/was a connect-only
handle) then disconnect before performing */
if(data->conn) {
struct connectdata *c;
curl_socket_t s;
Curl_detach_connection(data);
s = Curl_getconnectinfo(data, &c);
if((s != CURL_SOCKET_BAD) && c) {
Curl_cpool_disconnect(data, c, TRUE);
}
DEBUGASSERT(!data->conn);
}
if(data->multi_easy)
multi = data->multi_easy;
else {
/* this multi handle will only ever have a single easy handled attached
to it, so make it use minimal hashes */
multi = Curl_multi_handle(1, 3, 7);
/* this multi handle will only ever have a single easy handle attached to
it, so make it use minimal hash sizes */
multi = Curl_multi_handle(1, 3, 7, 3);
if(!multi)
return CURLE_OUT_OF_MEMORY;
}
@@ -1336,3 +1350,41 @@ CURLcode curl_easy_upkeep(CURL *d)
/* Use the common function to keep connections alive. */
return Curl_cpool_upkeep(data);
}
CURLcode curl_easy_ssls_import(CURL *d, const char *session_key,
const unsigned char *shmac, size_t shmac_len,
const unsigned char *sdata, size_t sdata_len)
{
#ifdef USE_SSLS_EXPORT
struct Curl_easy *data = d;
if(!GOOD_EASY_HANDLE(data))
return CURLE_BAD_FUNCTION_ARGUMENT;
return Curl_ssl_session_import(data, session_key,
shmac, shmac_len, sdata, sdata_len);
#else
(void)d;
(void)session_key;
(void)shmac;
(void)shmac_len;
(void)sdata;
(void)sdata_len;
return CURLE_NOT_BUILT_IN;
#endif
}
CURLcode curl_easy_ssls_export(CURL *d,
curl_ssls_export_cb *export_fn,
void *userptr)
{
#ifdef USE_SSLS_EXPORT
struct Curl_easy *data = d;
if(!GOOD_EASY_HANDLE(data))
return CURLE_BAD_FUNCTION_ARGUMENT;
return Curl_ssl_session_export(data, export_fn, userptr);
#else
(void)d;
(void)export_fn;
(void)userptr;
return CURLE_NOT_BUILT_IN;
#endif
}

View File

@@ -69,7 +69,7 @@
#endif
static inline void curl_simple_lock_lock(curl_simple_lock *lock)
static CURL_INLINE void curl_simple_lock_lock(curl_simple_lock *lock)
{
for(;;) {
if(!atomic_exchange_explicit(lock, true, memory_order_acquire))
@@ -81,6 +81,8 @@ static inline void curl_simple_lock_lock(curl_simple_lock *lock)
__builtin_ia32_pause();
#elif defined(__aarch64__)
__asm__ volatile("yield" ::: "memory");
#elif defined(_WIN32)
Sleep(1);
#elif defined(HAVE_SCHED_YIELD)
sched_yield();
#endif
@@ -88,7 +90,7 @@ static inline void curl_simple_lock_lock(curl_simple_lock *lock)
}
}
static inline void curl_simple_lock_unlock(curl_simple_lock *lock)
static CURL_INLINE void curl_simple_lock_unlock(curl_simple_lock *lock)
{
atomic_store_explicit(lock, false, memory_order_release);
}

View File

@@ -377,6 +377,6 @@ struct curl_easyoption Curl_easyopts[] = {
*/
int Curl_easyopts_check(void)
{
return ((CURLOPT_LASTENTRY%10000) != (326 + 1));
return (CURLOPT_LASTENTRY % 10000) != (326 + 1);
}
#endif

View File

@@ -78,18 +78,12 @@
#include "curl_memory.h"
#include "memdebug.h"
#if defined(_WIN32) || defined(MSDOS) || defined(__EMX__)
#if defined(_WIN32) || defined(MSDOS)
#define DOS_FILESYSTEM 1
#elif defined(__amigaos4__)
#define AMIGA_FILESYSTEM 1
#endif
#ifdef OPEN_NEEDS_ARG3
# define open_readonly(p,f) open((p),(f),(0))
#else
# define open_readonly(p,f) open((p),(f))
#endif
/*
* Forward declarations.
*/
@@ -126,6 +120,7 @@ const struct Curl_handler Curl_handler_file = {
ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
ZERO_NULL, /* follow */
0, /* defport */
CURLPROTO_FILE, /* protocol */
CURLPROTO_FILE, /* family */
@@ -209,7 +204,7 @@ static CURLcode file_connect(struct Curl_easy *data, bool *done)
return CURLE_URL_MALFORMAT;
}
fd = open_readonly(actual_path, O_RDONLY|O_BINARY);
fd = open(actual_path, O_RDONLY|CURL_O_BINARY);
file->path = actual_path;
#else
if(memchr(real_path, 0, real_path_len)) {
@@ -233,16 +228,16 @@ static CURLcode file_connect(struct Curl_easy *data, bool *done)
extern int __unix_path_semantics;
if(strchr(real_path + 1, ':')) {
/* Amiga absolute path */
fd = open_readonly(real_path + 1, O_RDONLY);
fd = open(real_path + 1, O_RDONLY);
file->path++;
}
else if(__unix_path_semantics) {
/* -lunix fallback */
fd = open_readonly(real_path, O_RDONLY);
fd = open(real_path, O_RDONLY);
}
}
#else
fd = open_readonly(real_path, O_RDONLY);
fd = open(real_path, O_RDONLY);
file->path = real_path;
#endif
#endif
@@ -318,18 +313,18 @@ static CURLcode file_upload(struct Curl_easy *data)
if(!dir[1])
return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */
#ifdef O_BINARY
#define MODE_DEFAULT O_WRONLY|O_CREAT|O_BINARY
#else
#define MODE_DEFAULT O_WRONLY|O_CREAT
#endif
mode = O_WRONLY|O_CREAT|CURL_O_BINARY;
if(data->state.resume_from)
mode = MODE_DEFAULT|O_APPEND;
mode |= O_APPEND;
else
mode = MODE_DEFAULT|O_TRUNC;
mode |= O_TRUNC;
#if (defined(ANDROID) || defined(__ANDROID__)) && \
(defined(__i386__) || defined(__arm__))
fd = open(file->path, mode, (mode_t)data->set.new_file_perms);
#else
fd = open(file->path, mode, data->set.new_file_perms);
#endif
if(fd < 0) {
failf(data, "cannot open %s for writing", file->path);
return CURLE_WRITE_ERROR;
@@ -553,8 +548,13 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
if(data->state.resume_from) {
if(!S_ISDIR(statbuf.st_mode)) {
#ifdef __AMIGA__
if(data->state.resume_from !=
lseek(fd, (off_t)data->state.resume_from, SEEK_SET))
#else
if(data->state.resume_from !=
lseek(fd, data->state.resume_from, SEEK_SET))
#endif
return CURLE_BAD_DOWNLOAD_RESUME;
}
else {

View File

@@ -53,7 +53,7 @@
#ifdef _WIN32
#define PATHSEP "\\"
#define IS_SEP(x) (((x) == '/') || ((x) == '\\'))
#elif defined(MSDOS) || defined(__EMX__) || defined(OS2)
#elif defined(MSDOS) || defined(OS2)
#define PATHSEP "\\"
#define IS_SEP(x) ((x) == '\\')
#else

View File

@@ -250,6 +250,7 @@ const struct Curl_handler Curl_handler_ftp = {
ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
ZERO_NULL, /* follow */
PORT_FTP, /* defport */
CURLPROTO_FTP, /* protocol */
CURLPROTO_FTP, /* family */
@@ -282,6 +283,7 @@ const struct Curl_handler Curl_handler_ftps = {
ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
ZERO_NULL, /* follow */
PORT_FTPS, /* defport */
CURLPROTO_FTPS, /* protocol */
CURLPROTO_FTP, /* family */
@@ -2079,10 +2081,19 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
/* If we asked for a time of the file and we actually got one as well,
we "emulate" an HTTP-style header in our output. */
#if defined(__GNUC__) && (defined(__DJGPP__) || defined(__AMIGA__))
#pragma GCC diagnostic push
/* 'time_t' is unsigned in MSDOS and AmigaOS. Silence:
warning: comparison of unsigned expression in '>= 0' is always true */
#pragma GCC diagnostic ignored "-Wtype-limits"
#endif
if(data->req.no_body &&
ftpc->file &&
data->set.get_filetime &&
(data->info.filetime >= 0) ) {
#if defined(__GNUC__) && (defined(__DJGPP__) || defined(__AMIGA__))
#pragma GCC diagnostic pop
#endif
char headerbuf[128];
int headerbuflen;
time_t filetime = data->info.filetime;
@@ -3154,7 +3165,7 @@ static CURLcode ftp_connect(struct Curl_easy *data,
PINGPONG_SETUP(pp, ftp_statemachine, ftp_endofresp);
if(conn->handler->flags & PROTOPT_SSL) {
if(Curl_conn_is_ssl(conn, FIRSTSOCKET)) {
/* BLOCKING */
result = Curl_conn_connect(data, FIRSTSOCKET, TRUE, done);
if(result)
@@ -4097,8 +4108,8 @@ static CURLcode ftp_disconnect(struct Curl_easy *data,
}
#ifdef _MSC_VER
/* warning C4706: assignment within conditional expression */
#pragma warning(disable:4706)
#pragma warning(push)
#pragma warning(disable:4706) /* assignment within conditional expression */
#endif
/***********************************************************************
@@ -4244,7 +4255,7 @@ CURLcode ftp_parse_url_path(struct Curl_easy *data)
else
n -= ftpc->file ? strlen(ftpc->file) : 0;
if((strlen(oldPath) == n) && !strncmp(rawPath, oldPath, n)) {
if((strlen(oldPath) == n) && rawPath && !strncmp(rawPath, oldPath, n)) {
infof(data, "Request has same path as previous transfer");
ftpc->cwddone = TRUE;
}
@@ -4255,6 +4266,10 @@ CURLcode ftp_parse_url_path(struct Curl_easy *data)
return CURLE_OK;
}
#ifdef _MSC_VER
#pragma warning(pop)
#endif
/* call this when the DO phase has completed */
static CURLcode ftp_dophase_done(struct Curl_easy *data, bool connected)
{

View File

@@ -62,6 +62,7 @@
/* int send(int, const char *, int, int); */
#define SEND_TYPE_ARG1 int
#define SEND_QUAL_ARG2
#define SEND_TYPE_ARG2 char *
#define SEND_TYPE_ARG3 int
#define SEND_TYPE_RETV int

View File

@@ -69,6 +69,8 @@ CURLcode Curl_initinfo(struct Curl_easy *data)
info->request_size = 0;
info->proxyauthavail = 0;
info->httpauthavail = 0;
info->proxyauthpicked = 0;
info->httpauthpicked = 0;
info->numconnects = 0;
free(info->contenttype);
@@ -238,8 +240,10 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
case CURLINFO_FILETIME:
if(data->info.filetime > LONG_MAX)
*param_longp = LONG_MAX;
#if !defined(MSDOS) && !defined(__AMIGA__)
else if(data->info.filetime < LONG_MIN)
*param_longp = LONG_MIN;
#endif
else
*param_longp = (long)data->info.filetime;
break;
@@ -270,6 +274,14 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
lptr.to_long = param_longp;
*lptr.to_ulong = data->info.proxyauthavail;
break;
case CURLINFO_HTTPAUTH_USED:
lptr.to_long = param_longp;
*lptr.to_ulong = data->info.httpauthpicked;
break;
case CURLINFO_PROXYAUTH_USED:
lptr.to_long = param_longp;
*lptr.to_ulong = data->info.proxyauthpicked;
break;
case CURLINFO_OS_ERRNO:
*param_longp = data->state.os_errno;
break;
@@ -377,6 +389,7 @@ static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
case CURLINFO_APPCONNECT_TIME_T:
case CURLINFO_PRETRANSFER_TIME_T:
case CURLINFO_POSTTRANSFER_TIME_T:
case CURLINFO_QUEUE_TIME_T:
case CURLINFO_STARTTRANSFER_TIME_T:
case CURLINFO_REDIRECT_TIME_T:
case CURLINFO_SPEED_DOWNLOAD_T:

View File

@@ -79,6 +79,7 @@ const struct Curl_handler Curl_handler_gopher = {
ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
ZERO_NULL, /* follow */
PORT_GOPHER, /* defport */
CURLPROTO_GOPHER, /* protocol */
CURLPROTO_GOPHER, /* family */
@@ -104,6 +105,7 @@ const struct Curl_handler Curl_handler_gophers = {
ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
ZERO_NULL, /* follow */
PORT_GOPHER, /* defport */
CURLPROTO_GOPHERS, /* protocol */
CURLPROTO_GOPHER, /* family */

View File

@@ -42,6 +42,8 @@ hash_element_dtor(void *user, void *element)
{
struct Curl_hash *h = (struct Curl_hash *) user;
struct Curl_hash_element *e = (struct Curl_hash_element *) element;
DEBUGASSERT(h);
DEBUGASSERT(e);
if(e->ptr) {
if(e->dtor)

View File

@@ -26,8 +26,9 @@
#include "curl_setup.h"
#if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI)) \
|| !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH)
#if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI)) || \
!defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH) || \
defined(USE_SSL)
#include <curl/curl.h>

View File

@@ -198,7 +198,7 @@ hostcache_entry_is_stale(void *datap, void *hc)
if(dns->timestamp) {
/* age in seconds */
time_t age = prune->now - dns->timestamp;
if(age >= prune->max_age_sec)
if(age >= (time_t)prune->max_age_sec)
return TRUE;
if(age > prune->oldest)
prune->oldest = age;
@@ -541,7 +541,9 @@ static struct Curl_addrinfo *get_localhost6(int port, const char *name)
sa6.sin6_family = AF_INET6;
sa6.sin6_port = htons(port16);
sa6.sin6_flowinfo = 0;
#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
sa6.sin6_scope_id = 0;
#endif
(void)Curl_inet_pton(AF_INET6, "::1", ipv6);
memcpy(&sa6.sin6_addr, ipv6, sizeof(ipv6));
@@ -630,7 +632,7 @@ bool Curl_ipv6works(struct Curl_easy *data)
ipv6_works = 1;
sclose(s);
}
return (ipv6_works > 0);
return ipv6_works > 0;
}
}
#endif /* USE_IPV6 */
@@ -1077,18 +1079,10 @@ static void hostcache_unlink_entry(void *entry)
Curl_freeaddrinfo(dns->addr);
#ifdef USE_HTTPSRR
if(dns->hinfo) {
if(dns->hinfo->target)
free(dns->hinfo->target);
if(dns->hinfo->alpns)
free(dns->hinfo->alpns);
if(dns->hinfo->ipv4hints)
free(dns->hinfo->ipv4hints);
if(dns->hinfo->echconfiglist)
free(dns->hinfo->echconfiglist);
if(dns->hinfo->ipv6hints)
free(dns->hinfo->ipv6hints);
if(dns->hinfo->val)
free(dns->hinfo->val);
free(dns->hinfo->target);
free(dns->hinfo->ipv4hints);
free(dns->hinfo->echconfiglist);
free(dns->hinfo->ipv6hints);
free(dns->hinfo);
}
#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>
@@ -53,6 +54,13 @@ struct hostent;
struct Curl_easy;
struct connectdata;
enum alpnid {
ALPN_none = 0,
ALPN_h1 = CURLALTSVC_H1,
ALPN_h2 = CURLALTSVC_H2,
ALPN_h3 = CURLALTSVC_H3
};
/*
* Curl_global_host_cache_init() initializes and sets up a global DNS cache.
* Global DNS cache is general badness. Do not use. This will be removed in
@@ -62,36 +70,6 @@ struct connectdata;
*/
struct Curl_hash *Curl_global_host_cache_init(void);
#ifdef USE_HTTPSRR
#define CURL_MAXLEN_host_name 253
struct Curl_https_rrinfo {
size_t len; /* raw encoded length */
unsigned char *val; /* raw encoded octets */
/*
* fields from HTTPS RR, with the mandatory fields
* first (priority, target), then the others in the
* order of the keytag numbers defined at
* https://datatracker.ietf.org/doc/html/rfc9460#section-14.3.2
*/
uint16_t priority;
char *target;
char *alpns; /* keytag = 1 */
bool no_def_alpn; /* keytag = 2 */
/*
* we do not support ports (keytag = 3) as we do not support
* port-switching yet
*/
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;
};
#endif
struct Curl_dns_entry {
struct Curl_addrinfo *addr;
#ifdef USE_HTTPSRR

View File

@@ -41,6 +41,7 @@
#include "rename.h"
#include "share.h"
#include "strdup.h"
#include "strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -48,10 +49,8 @@
#include "memdebug.h"
#define MAX_HSTS_LINE 4095
#define MAX_HSTS_HOSTLEN 256
#define MAX_HSTS_HOSTLENSTR "256"
#define MAX_HSTS_DATELEN 64
#define MAX_HSTS_DATELENSTR "64"
#define MAX_HSTS_HOSTLEN 2048
#define MAX_HSTS_DATELEN 256
#define UNLIMITED "unlimited"
#if defined(DEBUGBUILD) || defined(UNITTESTS)
@@ -109,14 +108,13 @@ void Curl_hsts_cleanup(struct hsts **hp)
static CURLcode hsts_create(struct hsts *h,
const char *hostname,
size_t hlen,
bool subdomains,
curl_off_t expires)
{
size_t hlen;
DEBUGASSERT(h);
DEBUGASSERT(hostname);
hlen = strlen(hostname);
if(hlen && (hostname[hlen - 1] == '.'))
/* strip off any trailing dot */
--hlen;
@@ -150,6 +148,7 @@ CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname,
bool subdomains = FALSE;
struct stsentry *sts;
time_t now = time(NULL);
size_t hlen = strlen(hostname);
if(Curl_host_is_ipnum(hostname))
/* "explicit IP address identification of all forms is excluded."
@@ -218,7 +217,7 @@ CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname,
if(!expires) {
/* remove the entry if present verbatim (without subdomain match) */
sts = Curl_hsts(h, hostname, FALSE);
sts = Curl_hsts(h, hostname, hlen, FALSE);
if(sts) {
Curl_node_remove(&sts->node);
hsts_free(sts);
@@ -233,14 +232,14 @@ CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname,
expires += now;
/* check if it already exists */
sts = Curl_hsts(h, hostname, FALSE);
sts = Curl_hsts(h, hostname, hlen, FALSE);
if(sts) {
/* just update these fields */
sts->expires = expires;
sts->includeSubDomains = subdomains;
}
else
return hsts_create(h, hostname, subdomains, expires);
return hsts_create(h, hostname, hlen, subdomains, expires);
return CURLE_OK;
}
@@ -252,12 +251,11 @@ CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname,
* attempted.
*/
struct stsentry *Curl_hsts(struct hsts *h, const char *hostname,
bool subdomain)
size_t hlen, bool subdomain)
{
struct stsentry *bestsub = NULL;
if(h) {
time_t now = time(NULL);
size_t hlen = strlen(hostname);
struct Curl_llist_node *e;
struct Curl_llist_node *n;
size_t blen = 0;
@@ -424,29 +422,40 @@ static CURLcode hsts_add(struct hsts *h, char *line)
example.com "20191231 10:00:00"
.example.net "20191231 10:00:00"
*/
char host[MAX_HSTS_HOSTLEN + 1];
char date[MAX_HSTS_DATELEN + 1];
int rc;
struct Curl_str host;
struct Curl_str date;
rc = sscanf(line,
"%" MAX_HSTS_HOSTLENSTR "s \"%" MAX_HSTS_DATELENSTR "[^\"]\"",
host, date);
if(2 == rc) {
time_t expires = strcmp(date, UNLIMITED) ? Curl_getdate_capped(date) :
TIME_T_MAX;
if(Curl_str_word(&line, &host, MAX_HSTS_HOSTLEN) ||
Curl_str_singlespace(&line) ||
Curl_str_quotedword(&line, &date, MAX_HSTS_DATELEN) ||
Curl_str_newline(&line))
;
else {
CURLcode result = CURLE_OK;
char *p = host;
bool subdomain = FALSE;
struct stsentry *e;
if(p[0] == '.') {
p++;
char dbuf[MAX_HSTS_DATELEN + 1];
time_t expires;
/* The date parser works on a null terminated string. The maximum length
is upheld by Curl_str_quotedword(). */
memcpy(dbuf, date.str, date.len);
dbuf[date.len] = 0;
expires = strcmp(dbuf, UNLIMITED) ? Curl_getdate_capped(dbuf) :
TIME_T_MAX;
if(host.str[0] == '.') {
host.str++;
host.len--;
subdomain = TRUE;
}
/* only add it if not already present */
e = Curl_hsts(h, p, subdomain);
e = Curl_hsts(h, host.str, host.len, subdomain);
if(!e)
result = hsts_create(h, p, subdomain, expires);
else if(strcasecompare(p, e->host)) {
result = hsts_create(h, host.str, host.len, subdomain, expires);
else if((strlen(e->host) == host.len) &&
strncasecompare(host.str, e->host, host.len)) {
/* the same hostname, use the largest expire time */
if(expires > e->expires)
e->expires = expires;
@@ -488,7 +497,7 @@ static CURLcode hsts_pull(struct Curl_easy *data, struct hsts *h)
expires = Curl_getdate_capped(e.expire);
else
expires = TIME_T_MAX; /* the end of time */
result = hsts_create(h, e.name,
result = hsts_create(h, e.name, strlen(e.name),
/* bitfield to bool conversion: */
e.includeSubDomains ? TRUE : FALSE,
expires);

View File

@@ -52,7 +52,7 @@ void Curl_hsts_cleanup(struct hsts **hp);
CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname,
const char *sts);
struct stsentry *Curl_hsts(struct hsts *h, const char *hostname,
bool subdomain);
size_t hlen, bool subdomain);
CURLcode Curl_hsts_save(struct Curl_easy *data, struct hsts *h,
const char *file);
CURLcode Curl_hsts_loadfile(struct Curl_easy *data,

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More