mirror of
https://gitlab.kitware.com/cmake/cmake.git
synced 2026-09-25 04:09:36 +03:00
curl 2024-09-18 (7eb8c048)
Code extracted from:
https://github.com/curl/curl.git
at commit 7eb8c048470ed2cc14dca75be9c1cdae7ac8498b (curl-8_10_1).
This commit is contained in:
@@ -23,7 +23,7 @@
|
||||
###########################################################################
|
||||
include(CheckCSourceCompiles)
|
||||
|
||||
option(CURL_HIDDEN_SYMBOLS "Set to ON to hide libcurl internal symbols (=hide all symbols that aren't officially external)." ON)
|
||||
option(CURL_HIDDEN_SYMBOLS "Hide libcurl internal symbols (=hide all symbols that are not officially external)" ON)
|
||||
mark_as_advanced(CURL_HIDDEN_SYMBOLS)
|
||||
|
||||
if(WIN32 AND (ENABLE_DEBUG OR ENABLE_CURLDEBUG))
|
||||
@@ -34,52 +34,47 @@ if(WIN32 AND (ENABLE_DEBUG OR ENABLE_CURLDEBUG))
|
||||
endif()
|
||||
|
||||
if(CURL_HIDDEN_SYMBOLS)
|
||||
set(SUPPORTS_SYMBOL_HIDING FALSE)
|
||||
set(_supports_symbol_hiding FALSE)
|
||||
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "Clang" AND NOT MSVC)
|
||||
set(SUPPORTS_SYMBOL_HIDING TRUE)
|
||||
set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
|
||||
set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
|
||||
set(_supports_symbol_hiding TRUE)
|
||||
set(_symbol_extern "__attribute__ ((__visibility__ (\"default\")))")
|
||||
set(_cflag_symbols_hide "-fvisibility=hidden")
|
||||
elseif(CMAKE_COMPILER_IS_GNUCC)
|
||||
if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4)
|
||||
# note: this is considered buggy prior to 4.0 but the autotools don't care, so let's ignore that fact
|
||||
set(SUPPORTS_SYMBOL_HIDING TRUE)
|
||||
set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
|
||||
set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
|
||||
# Note: This is considered buggy prior to 4.0 but the autotools do not care, so let us ignore that fact
|
||||
set(_supports_symbol_hiding TRUE)
|
||||
set(_symbol_extern "__attribute__ ((__visibility__ (\"default\")))")
|
||||
set(_cflag_symbols_hide "-fvisibility=hidden")
|
||||
endif()
|
||||
elseif(CMAKE_C_COMPILER_ID MATCHES "SunPro" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 8.0)
|
||||
set(SUPPORTS_SYMBOL_HIDING TRUE)
|
||||
set(_SYMBOL_EXTERN "__global")
|
||||
set(_CFLAG_SYMBOLS_HIDE "-xldscope=hidden")
|
||||
set(_supports_symbol_hiding TRUE)
|
||||
set(_symbol_extern "__global")
|
||||
set(_cflag_symbols_hide "-xldscope=hidden")
|
||||
elseif(CMAKE_C_COMPILER_ID MATCHES "Intel" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 9.0)
|
||||
# note: this should probably just check for version 9.1.045 but I'm not 100% sure
|
||||
# so let's do it the same way autotools do.
|
||||
set(SUPPORTS_SYMBOL_HIDING TRUE)
|
||||
set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
|
||||
set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
|
||||
# Note: This should probably just check for version 9.1.045 but I am not 100% sure
|
||||
# so let us do it the same way autotools do.
|
||||
set(_supports_symbol_hiding TRUE)
|
||||
set(_symbol_extern "__attribute__ ((__visibility__ (\"default\")))")
|
||||
set(_cflag_symbols_hide "-fvisibility=hidden")
|
||||
check_c_source_compiles("#include <stdio.h>
|
||||
int main (void) { printf(\"icc fvisibility bug test\"); return 0; }" _no_bug)
|
||||
int main(void) { printf(\"icc fvisibility bug test\"); return 0; }" _no_bug)
|
||||
if(NOT _no_bug)
|
||||
set(SUPPORTS_SYMBOL_HIDING FALSE)
|
||||
set(_SYMBOL_EXTERN "")
|
||||
set(_CFLAG_SYMBOLS_HIDE "")
|
||||
set(_supports_symbol_hiding FALSE)
|
||||
set(_symbol_extern "")
|
||||
set(_cflag_symbols_hide "")
|
||||
endif()
|
||||
elseif(MSVC)
|
||||
set(SUPPORTS_SYMBOL_HIDING TRUE)
|
||||
set(_supports_symbol_hiding TRUE)
|
||||
endif()
|
||||
|
||||
set(HIDES_CURL_PRIVATE_SYMBOLS ${SUPPORTS_SYMBOL_HIDING})
|
||||
elseif(MSVC)
|
||||
if(NOT CMAKE_VERSION VERSION_LESS 3.7)
|
||||
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE) #present since 3.4.3 but broken
|
||||
set(HIDES_CURL_PRIVATE_SYMBOLS FALSE)
|
||||
else()
|
||||
message(WARNING "Hiding private symbols regardless CURL_HIDDEN_SYMBOLS being disabled.")
|
||||
set(HIDES_CURL_PRIVATE_SYMBOLS TRUE)
|
||||
endif()
|
||||
set(CURL_HIDES_PRIVATE_SYMBOLS ${_supports_symbol_hiding})
|
||||
else()
|
||||
set(HIDES_CURL_PRIVATE_SYMBOLS FALSE)
|
||||
if(MSVC)
|
||||
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
|
||||
endif()
|
||||
set(CURL_HIDES_PRIVATE_SYMBOLS FALSE)
|
||||
endif()
|
||||
|
||||
set(CURL_CFLAG_SYMBOLS_HIDE ${_CFLAG_SYMBOLS_HIDE})
|
||||
set(CURL_EXTERN_SYMBOL ${_SYMBOL_EXTERN})
|
||||
set(CURL_CFLAG_SYMBOLS_HIDE ${_cflag_symbols_hide})
|
||||
set(CURL_EXTERN_SYMBOL ${_symbol_extern})
|
||||
|
||||
+2
-2
@@ -152,7 +152,7 @@ int main(void) { return 0; }
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#include <sys/types.h>
|
||||
/* Check that off_t can represent 2**63 - 1 correctly.
|
||||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
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))
|
||||
@@ -337,7 +337,7 @@ int main(void)
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* float, because a pointer can't be implicitly cast to float */
|
||||
/* Float, because a pointer cannot be implicitly cast to float */
|
||||
void check(float f) {}
|
||||
|
||||
int main(void)
|
||||
|
||||
+32
-5
@@ -21,12 +21,39 @@
|
||||
# SPDX-License-Identifier: curl
|
||||
#
|
||||
###########################################################################
|
||||
find_path(BEARSSL_INCLUDE_DIRS bearssl.h)
|
||||
# Find the bearssl library
|
||||
#
|
||||
# Input variables:
|
||||
#
|
||||
# BEARSSL_INCLUDE_DIR The bearssl include directory
|
||||
# BEARSSL_INCLUDE_DIRS The bearssl include directory (deprecated)
|
||||
# BEARSSL_LIBRARY Path to bearssl library
|
||||
#
|
||||
# Result variables:
|
||||
#
|
||||
# BEARSSL_FOUND System has bearssl
|
||||
# BEARSSL_INCLUDE_DIRS The bearssl include directories
|
||||
# BEARSSL_LIBRARIES The bearssl library names
|
||||
|
||||
find_library(BEARSSL_LIBRARY bearssl)
|
||||
if(DEFINED BEARSSL_INCLUDE_DIRS AND NOT DEFINED BEARSSL_INCLUDE_DIR)
|
||||
message(WARNING "BEARSSL_INCLUDE_DIRS is deprecated, use BEARSSL_INCLUDE_DIR instead.")
|
||||
set(BEARSSL_INCLUDE_DIR "${BEARSSL_INCLUDE_DIRS}")
|
||||
unset(BEARSSL_INCLUDE_DIRS)
|
||||
endif()
|
||||
|
||||
find_path(BEARSSL_INCLUDE_DIR NAMES "bearssl.h")
|
||||
find_library(BEARSSL_LIBRARY NAMES "bearssl")
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(BEARSSL DEFAULT_MSG
|
||||
BEARSSL_INCLUDE_DIRS BEARSSL_LIBRARY)
|
||||
find_package_handle_standard_args(BearSSL
|
||||
REQUIRED_VARS
|
||||
BEARSSL_INCLUDE_DIR
|
||||
BEARSSL_LIBRARY
|
||||
)
|
||||
|
||||
mark_as_advanced(BEARSSL_INCLUDE_DIRS BEARSSL_LIBRARY)
|
||||
if(BEARSSL_FOUND)
|
||||
set(BEARSSL_INCLUDE_DIRS ${BEARSSL_INCLUDE_DIR})
|
||||
set(BEARSSL_LIBRARIES ${BEARSSL_LIBRARY})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(BEARSSL_INCLUDE_DIR BEARSSL_LIBRARY)
|
||||
|
||||
+53
-16
@@ -21,23 +21,60 @@
|
||||
# SPDX-License-Identifier: curl
|
||||
#
|
||||
###########################################################################
|
||||
include(FindPackageHandleStandardArgs)
|
||||
# Find the brotli library
|
||||
#
|
||||
# Input variables:
|
||||
#
|
||||
# BROTLI_INCLUDE_DIR The brotli include directory
|
||||
# BROTLICOMMON_LIBRARY Path to brotlicommon library
|
||||
# BROTLIDEC_LIBRARY Path to brotlidec library
|
||||
#
|
||||
# Result variables:
|
||||
#
|
||||
# BROTLI_FOUND System has brotli
|
||||
# BROTLI_INCLUDE_DIRS The brotli include directories
|
||||
# BROTLI_LIBRARIES The brotli library names
|
||||
# BROTLI_VERSION Version of brotli
|
||||
|
||||
find_path(BROTLI_INCLUDE_DIR "brotli/decode.h")
|
||||
if(CURL_USE_PKGCONFIG)
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PC_BROTLI "libbrotlidec")
|
||||
endif()
|
||||
|
||||
find_library(BROTLICOMMON_LIBRARY NAMES brotlicommon)
|
||||
find_library(BROTLIDEC_LIBRARY NAMES brotlidec)
|
||||
|
||||
find_package_handle_standard_args(Brotli
|
||||
FOUND_VAR
|
||||
BROTLI_FOUND
|
||||
REQUIRED_VARS
|
||||
BROTLIDEC_LIBRARY
|
||||
BROTLICOMMON_LIBRARY
|
||||
BROTLI_INCLUDE_DIR
|
||||
FAIL_MESSAGE
|
||||
"Could NOT find Brotli"
|
||||
find_path(BROTLI_INCLUDE_DIR "brotli/decode.h"
|
||||
HINTS
|
||||
${PC_BROTLI_INCLUDEDIR}
|
||||
${PC_BROTLI_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
set(BROTLI_INCLUDE_DIRS ${BROTLI_INCLUDE_DIR})
|
||||
set(BROTLI_LIBRARIES ${BROTLIDEC_LIBRARY} ${BROTLICOMMON_LIBRARY})
|
||||
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}
|
||||
)
|
||||
|
||||
if(PC_BROTLI_VERSION)
|
||||
set(BROTLI_VERSION ${PC_BROTLI_VERSION})
|
||||
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)
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
#***************************************************************************
|
||||
# _ _ ____ _
|
||||
# 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 c-ares
|
||||
# Find the c-ares includes and library
|
||||
# This module defines
|
||||
# CARES_INCLUDE_DIR, where to find ares.h, etc.
|
||||
# CARES_LIBRARIES, the libraries needed to use c-ares.
|
||||
# CARES_FOUND, If false, do not try to use c-ares.
|
||||
# also defined, but not for general use are
|
||||
# CARES_LIBRARY, where to find the c-ares library.
|
||||
|
||||
find_path(CARES_INCLUDE_DIR ares.h)
|
||||
|
||||
set(CARES_NAMES ${CARES_NAMES} cares)
|
||||
find_library(CARES_LIBRARY
|
||||
NAMES ${CARES_NAMES}
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(CARES
|
||||
REQUIRED_VARS CARES_LIBRARY CARES_INCLUDE_DIR)
|
||||
|
||||
mark_as_advanced(
|
||||
CARES_LIBRARY
|
||||
CARES_INCLUDE_DIR
|
||||
)
|
||||
@@ -0,0 +1,80 @@
|
||||
#***************************************************************************
|
||||
# _ _ ____ _
|
||||
# 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 c-ares library
|
||||
#
|
||||
# Input variables:
|
||||
#
|
||||
# CARES_INCLUDE_DIR The c-ares include directory
|
||||
# CARES_LIBRARY Path to c-ares library
|
||||
#
|
||||
# Result variables:
|
||||
#
|
||||
# CARES_FOUND System has c-ares
|
||||
# CARES_INCLUDE_DIRS The c-ares include directories
|
||||
# CARES_LIBRARIES The c-ares library names
|
||||
# CARES_VERSION Version of c-ares
|
||||
|
||||
if(CURL_USE_PKGCONFIG)
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PC_CARES "libcares")
|
||||
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_regex "#[\t ]*define[\t ]+ARES_VERSION_STR[\t ]+\"([^\"]*)\"")
|
||||
file(STRINGS "${CARES_INCLUDE_DIR}/ares_version.h" _version_str REGEX "${_version_regex}")
|
||||
string(REGEX REPLACE "${_version_regex}" "\\1" _version_str "${_version_str}")
|
||||
set(CARES_VERSION "${_version_str}")
|
||||
unset(_version_regex)
|
||||
unset(_version_str)
|
||||
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)
|
||||
+138
-129
@@ -21,275 +21,276 @@
|
||||
# SPDX-License-Identifier: curl
|
||||
#
|
||||
###########################################################################
|
||||
# - Try to find the GSS Kerberos library
|
||||
# Once done this will define
|
||||
# Find the GSS Kerberos library
|
||||
#
|
||||
# GSS_ROOT_DIR - Set this variable to the root installation of GSS
|
||||
# Input variables:
|
||||
#
|
||||
# Read-Only variables:
|
||||
# GSS_FOUND - system has the Heimdal library
|
||||
# GSS_FLAVOUR - "MIT" or "Heimdal" if anything found.
|
||||
# GSS_INCLUDE_DIR - the Heimdal include directory
|
||||
# GSS_LIBRARIES - The libraries needed to use GSS
|
||||
# GSS_LINK_DIRECTORIES - Directories to add to linker search path
|
||||
# GSS_LINKER_FLAGS - Additional linker flags
|
||||
# GSS_COMPILER_FLAGS - Additional compiler flags
|
||||
# GSS_VERSION - This is set to version advertised by pkg-config or read from manifest.
|
||||
# In case the library is found but no version info available it'll be set to "unknown"
|
||||
# GSS_ROOT_DIR Set this variable to the root installation of GSS
|
||||
#
|
||||
# Result variables:
|
||||
#
|
||||
# GSS_FOUND System has the Heimdal library
|
||||
# GSS_FLAVOUR "MIT" or "Heimdal" if anything found
|
||||
# GSS_INCLUDE_DIRS The GSS include directories
|
||||
# GSS_LIBRARIES The GSS library names
|
||||
# GSS_LIBRARY_DIRS The GSS library directories
|
||||
# GSS_LDFLAGS Required linker flags
|
||||
# GSS_CFLAGS Required compiler flags
|
||||
# GSS_VERSION This is set to version advertised by pkg-config or read from manifest.
|
||||
# In case the library is found but no version info available it is set to "unknown"
|
||||
|
||||
set(_MIT_MODNAME mit-krb5-gssapi)
|
||||
set(_HEIMDAL_MODNAME heimdal-gssapi)
|
||||
set(_mit_modname "mit-krb5-gssapi")
|
||||
set(_heimdal_modname "heimdal-gssapi")
|
||||
|
||||
include(CheckIncludeFile)
|
||||
include(CheckIncludeFiles)
|
||||
include(CheckTypeSize)
|
||||
|
||||
set(_GSS_ROOT_HINTS
|
||||
set(_gss_root_hints
|
||||
"${GSS_ROOT_DIR}"
|
||||
"$ENV{GSS_ROOT_DIR}"
|
||||
)
|
||||
|
||||
# try to find library using system pkg-config if user didn't specify root dir
|
||||
# Try to find library using system pkg-config if user did not specify root dir
|
||||
if(NOT GSS_ROOT_DIR AND NOT "$ENV{GSS_ROOT_DIR}")
|
||||
if(UNIX)
|
||||
if(CURL_USE_PKGCONFIG)
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_search_module(_GSS_PKG ${_MIT_MODNAME} ${_HEIMDAL_MODNAME})
|
||||
list(APPEND _GSS_ROOT_HINTS "${_GSS_PKG_PREFIX}")
|
||||
elseif(WIN32)
|
||||
list(APPEND _GSS_ROOT_HINTS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos;InstallDir]")
|
||||
pkg_search_module(_GSS ${_mit_modname} ${_heimdal_modname})
|
||||
list(APPEND _gss_root_hints "${_GSS_PREFIX}")
|
||||
endif()
|
||||
if(WIN32)
|
||||
list(APPEND _gss_root_hints "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos;InstallDir]")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT _GSS_FOUND) #not found by pkg-config. Let's take more traditional approach.
|
||||
find_file(_GSS_CONFIGURE_SCRIPT
|
||||
if(NOT _GSS_FOUND) # Not found by pkg-config. Let us take more traditional approach.
|
||||
find_file(_gss_configure_script
|
||||
NAMES
|
||||
"krb5-config"
|
||||
HINTS
|
||||
${_GSS_ROOT_HINTS}
|
||||
${_gss_root_hints}
|
||||
PATH_SUFFIXES
|
||||
bin
|
||||
"bin"
|
||||
NO_CMAKE_PATH
|
||||
NO_CMAKE_ENVIRONMENT_PATH
|
||||
)
|
||||
|
||||
# if not found in user-supplied directories, maybe system knows better
|
||||
find_file(_GSS_CONFIGURE_SCRIPT
|
||||
# If not found in user-supplied directories, maybe system knows better
|
||||
find_file(_gss_configure_script
|
||||
NAMES
|
||||
"krb5-config"
|
||||
PATH_SUFFIXES
|
||||
bin
|
||||
"bin"
|
||||
)
|
||||
|
||||
if(_GSS_CONFIGURE_SCRIPT)
|
||||
if(_gss_configure_script)
|
||||
execute_process(
|
||||
COMMAND ${_GSS_CONFIGURE_SCRIPT} "--cflags" "gssapi"
|
||||
COMMAND ${_gss_configure_script} "--cflags" "gssapi"
|
||||
OUTPUT_VARIABLE _GSS_CFLAGS
|
||||
RESULT_VARIABLE _GSS_CONFIGURE_FAILED
|
||||
RESULT_VARIABLE _gss_configure_failed
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
message(STATUS "CFLAGS: ${_GSS_CFLAGS}")
|
||||
if(NOT _GSS_CONFIGURE_FAILED) # 0 means success
|
||||
# should also work in an odd case when multiple directories are given
|
||||
)
|
||||
message(STATUS "FindGSS CFLAGS: ${_GSS_CFLAGS}")
|
||||
if(NOT _gss_configure_failed) # 0 means success
|
||||
# Should also work in an odd case when multiple directories are given
|
||||
string(STRIP "${_GSS_CFLAGS}" _GSS_CFLAGS)
|
||||
string(REGEX REPLACE " +-I" ";" _GSS_CFLAGS "${_GSS_CFLAGS}")
|
||||
string(REGEX REPLACE " +-([^I][^ \\t;]*)" ";-\\1" _GSS_CFLAGS "${_GSS_CFLAGS}")
|
||||
|
||||
foreach(_flag ${_GSS_CFLAGS})
|
||||
foreach(_flag IN LISTS _GSS_CFLAGS)
|
||||
if(_flag MATCHES "^-I.*")
|
||||
string(REGEX REPLACE "^-I" "" _val "${_flag}")
|
||||
list(APPEND _GSS_INCLUDE_DIR "${_val}")
|
||||
list(APPEND _GSS_INCLUDE_DIRS "${_val}")
|
||||
else()
|
||||
list(APPEND _GSS_COMPILER_FLAGS "${_flag}")
|
||||
list(APPEND _GSS_CFLAGS "${_flag}")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND ${_GSS_CONFIGURE_SCRIPT} "--libs" "gssapi"
|
||||
OUTPUT_VARIABLE _GSS_LIB_FLAGS
|
||||
RESULT_VARIABLE _GSS_CONFIGURE_FAILED
|
||||
COMMAND ${_gss_configure_script} "--libs" "gssapi"
|
||||
OUTPUT_VARIABLE _gss_lib_flags
|
||||
RESULT_VARIABLE _gss_configure_failed
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
message(STATUS "LDFLAGS: ${_GSS_LIB_FLAGS}")
|
||||
message(STATUS "FindGSS LDFLAGS: ${_gss_lib_flags}")
|
||||
|
||||
if(NOT _GSS_CONFIGURE_FAILED) # 0 means success
|
||||
# this script gives us libraries and link directories. Blah. We have to deal with it.
|
||||
string(STRIP "${_GSS_LIB_FLAGS}" _GSS_LIB_FLAGS)
|
||||
string(REGEX REPLACE " +-(L|l)" ";-\\1" _GSS_LIB_FLAGS "${_GSS_LIB_FLAGS}")
|
||||
string(REGEX REPLACE " +-([^Ll][^ \\t;]*)" ";-\\1" _GSS_LIB_FLAGS "${_GSS_LIB_FLAGS}")
|
||||
if(NOT _gss_configure_failed) # 0 means success
|
||||
# This script gives us libraries and link directories. Blah. We have to deal with it.
|
||||
string(STRIP "${_gss_lib_flags}" _gss_lib_flags)
|
||||
string(REGEX REPLACE " +-(L|l)" ";-\\1" _gss_lib_flags "${_gss_lib_flags}")
|
||||
string(REGEX REPLACE " +-([^Ll][^ \\t;]*)" ";-\\1" _gss_lib_flags "${_gss_lib_flags}")
|
||||
|
||||
foreach(_flag ${_GSS_LIB_FLAGS})
|
||||
foreach(_flag IN LISTS _gss_lib_flags)
|
||||
if(_flag MATCHES "^-l.*")
|
||||
string(REGEX REPLACE "^-l" "" _val "${_flag}")
|
||||
list(APPEND _GSS_LIBRARIES "${_val}")
|
||||
elseif(_flag MATCHES "^-L.*")
|
||||
string(REGEX REPLACE "^-L" "" _val "${_flag}")
|
||||
list(APPEND _GSS_LINK_DIRECTORIES "${_val}")
|
||||
list(APPEND _GSS_LIBRARY_DIRS "${_val}")
|
||||
else()
|
||||
list(APPEND _GSS_LINKER_FLAGS "${_flag}")
|
||||
list(APPEND _GSS_LDFLAGS "${_flag}")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND ${_GSS_CONFIGURE_SCRIPT} "--version"
|
||||
COMMAND ${_gss_configure_script} "--version"
|
||||
OUTPUT_VARIABLE _GSS_VERSION
|
||||
RESULT_VARIABLE _GSS_CONFIGURE_FAILED
|
||||
RESULT_VARIABLE _gss_configure_failed
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
# older versions may not have the "--version" parameter. In this case we just don't care.
|
||||
if(_GSS_CONFIGURE_FAILED)
|
||||
# Older versions may not have the "--version" parameter. In this case we just do not care.
|
||||
if(_gss_configure_failed)
|
||||
set(_GSS_VERSION 0)
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND ${_GSS_CONFIGURE_SCRIPT} "--vendor"
|
||||
OUTPUT_VARIABLE _GSS_VENDOR
|
||||
RESULT_VARIABLE _GSS_CONFIGURE_FAILED
|
||||
COMMAND ${_gss_configure_script} "--vendor"
|
||||
OUTPUT_VARIABLE _gss_vendor
|
||||
RESULT_VARIABLE _gss_configure_failed
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
# older versions may not have the "--vendor" parameter. In this case we just don't care.
|
||||
if(_GSS_CONFIGURE_FAILED)
|
||||
set(GSS_FLAVOUR "Heimdal") # most probably, shouldn't really matter
|
||||
# Older versions may not have the "--vendor" parameter. In this case we just do not care.
|
||||
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")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
else() # either there is no config script or we are on a platform that doesn't provide one (Windows?)
|
||||
else() # Either there is no config script or we are on a platform that does not provide one (Windows?)
|
||||
|
||||
find_path(_GSS_INCLUDE_DIR
|
||||
NAMES
|
||||
"gssapi/gssapi.h"
|
||||
find_path(_GSS_INCLUDE_DIRS NAMES "gssapi/gssapi.h"
|
||||
HINTS
|
||||
${_GSS_ROOT_HINTS}
|
||||
${_gss_root_hints}
|
||||
PATH_SUFFIXES
|
||||
include
|
||||
inc
|
||||
"include"
|
||||
"inc"
|
||||
)
|
||||
|
||||
if(_GSS_INCLUDE_DIR) #jay, we've found something
|
||||
set(CMAKE_REQUIRED_INCLUDES "${_GSS_INCLUDE_DIR}")
|
||||
check_include_files( "gssapi/gssapi_generic.h;gssapi/gssapi_krb5.h" _GSS_HAVE_MIT_HEADERS)
|
||||
if(_GSS_INCLUDE_DIRS) # jay, we have found something
|
||||
set(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)
|
||||
if(_gss_have_mit_headers)
|
||||
set(GSS_FLAVOUR "MIT")
|
||||
else()
|
||||
# prevent compiling the header - just check if we can include it
|
||||
list(APPEND CMAKE_REQUIRED_DEFINITIONS -D__ROKEN_H__)
|
||||
check_include_file( "roken.h" _GSS_HAVE_ROKEN_H)
|
||||
# Prevent compiling the header - just check if we can include it
|
||||
list(APPEND CMAKE_REQUIRED_DEFINITIONS "-D__ROKEN_H__")
|
||||
check_include_file("roken.h" _gss_have_roken_h)
|
||||
|
||||
check_include_file( "heimdal/roken.h" _GSS_HAVE_HEIMDAL_ROKEN_H)
|
||||
if(_GSS_HAVE_ROKEN_H OR _GSS_HAVE_HEIMDAL_ROKEN_H)
|
||||
check_include_file("heimdal/roken.h" _gss_have_heimdal_roken_h)
|
||||
if(_gss_have_roken_h OR _gss_have_heimdal_roken_h)
|
||||
set(GSS_FLAVOUR "Heimdal")
|
||||
endif()
|
||||
list(REMOVE_ITEM CMAKE_REQUIRED_DEFINITIONS -D__ROKEN_H__)
|
||||
list(REMOVE_ITEM CMAKE_REQUIRED_DEFINITIONS "-D__ROKEN_H__")
|
||||
endif()
|
||||
else()
|
||||
# I'm not convinced if this is the right way but this is what autotools do at the moment
|
||||
find_path(_GSS_INCLUDE_DIR
|
||||
NAMES
|
||||
"gssapi.h"
|
||||
# I am not convinced if this is the right way but this is what autotools do at the moment
|
||||
find_path(_GSS_INCLUDE_DIRS NAMES "gssapi.h"
|
||||
HINTS
|
||||
${_GSS_ROOT_HINTS}
|
||||
${_gss_root_hints}
|
||||
PATH_SUFFIXES
|
||||
include
|
||||
inc
|
||||
"include"
|
||||
"inc"
|
||||
)
|
||||
|
||||
if(_GSS_INCLUDE_DIR)
|
||||
if(_GSS_INCLUDE_DIRS)
|
||||
set(GSS_FLAVOUR "Heimdal")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# if we have headers, check if we can link libraries
|
||||
# If we have headers, check if we can link libraries
|
||||
if(GSS_FLAVOUR)
|
||||
set(_GSS_LIBDIR_SUFFIXES "")
|
||||
set(_GSS_LIBDIR_HINTS ${_GSS_ROOT_HINTS})
|
||||
get_filename_component(_GSS_CALCULATED_POTENTIAL_ROOT "${_GSS_INCLUDE_DIR}" PATH)
|
||||
list(APPEND _GSS_LIBDIR_HINTS ${_GSS_CALCULATED_POTENTIAL_ROOT})
|
||||
set(_gss_libdir_suffixes "")
|
||||
set(_gss_libdir_hints ${_gss_root_hints})
|
||||
get_filename_component(_gss_calculated_potential_root "${_GSS_INCLUDE_DIRS}" DIRECTORY)
|
||||
list(APPEND _gss_libdir_hints ${_gss_calculated_potential_root})
|
||||
|
||||
if(WIN32)
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
list(APPEND _GSS_LIBDIR_SUFFIXES "lib/AMD64")
|
||||
list(APPEND _gss_libdir_suffixes "lib/AMD64")
|
||||
if(GSS_FLAVOUR STREQUAL "MIT")
|
||||
set(_GSS_LIBNAME "gssapi64")
|
||||
set(_gss_libname "gssapi64")
|
||||
else()
|
||||
set(_GSS_LIBNAME "libgssapi")
|
||||
set(_gss_libname "libgssapi")
|
||||
endif()
|
||||
else()
|
||||
list(APPEND _GSS_LIBDIR_SUFFIXES "lib/i386")
|
||||
list(APPEND _gss_libdir_suffixes "lib/i386")
|
||||
if(GSS_FLAVOUR STREQUAL "MIT")
|
||||
set(_GSS_LIBNAME "gssapi32")
|
||||
set(_gss_libname "gssapi32")
|
||||
else()
|
||||
set(_GSS_LIBNAME "libgssapi")
|
||||
set(_gss_libname "libgssapi")
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
list(APPEND _GSS_LIBDIR_SUFFIXES "lib;lib64") # those suffixes are not checked for HINTS
|
||||
list(APPEND _gss_libdir_suffixes "lib;lib64") # those suffixes are not checked for HINTS
|
||||
if(GSS_FLAVOUR STREQUAL "MIT")
|
||||
set(_GSS_LIBNAME "gssapi_krb5")
|
||||
set(_gss_libname "gssapi_krb5")
|
||||
else()
|
||||
set(_GSS_LIBNAME "gssapi")
|
||||
set(_gss_libname "gssapi")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_library(_GSS_LIBRARIES
|
||||
NAMES
|
||||
${_GSS_LIBNAME}
|
||||
find_library(_GSS_LIBRARIES NAMES ${_gss_libname}
|
||||
HINTS
|
||||
${_GSS_LIBDIR_HINTS}
|
||||
${_gss_libdir_hints}
|
||||
PATH_SUFFIXES
|
||||
${_GSS_LIBDIR_SUFFIXES}
|
||||
${_gss_libdir_suffixes}
|
||||
)
|
||||
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
if(_GSS_PKG_${_MIT_MODNAME}_VERSION)
|
||||
if(_GSS_MODULE_NAME STREQUAL _mit_modname OR _GSS_${_mit_modname}_VERSION) # _GSS_MODULE_NAME set since CMake 3.16
|
||||
set(GSS_FLAVOUR "MIT")
|
||||
set(_GSS_VERSION _GSS_PKG_${_MIT_MODNAME}_VERSION)
|
||||
if(NOT _GSS_VERSION) # for old CMake versions?
|
||||
set(_GSS_VERSION ${_GSS_${_mit_modname}_VERSION})
|
||||
endif()
|
||||
else()
|
||||
set(GSS_FLAVOUR "Heimdal")
|
||||
set(_GSS_VERSION _GSS_PKG_${_MIT_HEIMDAL}_VERSION)
|
||||
if(NOT _GSS_VERSION) # for old CMake versions?
|
||||
set(_GSS_VERSION ${_GSS_${_heimdal_modname}_VERSION})
|
||||
endif()
|
||||
endif()
|
||||
message(STATUS "Found GSS/${GSS_FLAVOUR} (via pkg-config): ${_GSS_INCLUDE_DIRS} (found version \"${_GSS_VERSION}\")")
|
||||
endif()
|
||||
|
||||
set(GSS_INCLUDE_DIR ${_GSS_INCLUDE_DIR})
|
||||
set(GSS_INCLUDE_DIRS ${_GSS_INCLUDE_DIRS})
|
||||
set(GSS_LIBRARIES ${_GSS_LIBRARIES})
|
||||
set(GSS_LINK_DIRECTORIES ${_GSS_LINK_DIRECTORIES})
|
||||
set(GSS_LINKER_FLAGS ${_GSS_LINKER_FLAGS})
|
||||
set(GSS_COMPILER_FLAGS ${_GSS_COMPILER_FLAGS})
|
||||
set(GSS_LIBRARY_DIRS ${_GSS_LIBRARY_DIRS})
|
||||
set(GSS_LDFLAGS ${_GSS_LDFLAGS})
|
||||
set(GSS_CFLAGS ${_GSS_CFLAGS})
|
||||
set(GSS_VERSION ${_GSS_VERSION})
|
||||
|
||||
if(GSS_FLAVOUR)
|
||||
if(NOT GSS_VERSION AND GSS_FLAVOUR STREQUAL "Heimdal")
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(HEIMDAL_MANIFEST_FILE "Heimdal.Application.amd64.manifest")
|
||||
set(_heimdal_manifest_file "Heimdal.Application.amd64.manifest")
|
||||
else()
|
||||
set(HEIMDAL_MANIFEST_FILE "Heimdal.Application.x86.manifest")
|
||||
set(_heimdal_manifest_file "Heimdal.Application.x86.manifest")
|
||||
endif()
|
||||
|
||||
if(EXISTS "${GSS_INCLUDE_DIR}/${HEIMDAL_MANIFEST_FILE}")
|
||||
file(STRINGS "${GSS_INCLUDE_DIR}/${HEIMDAL_MANIFEST_FILE}" heimdal_version_str
|
||||
REGEX "^.*version=\"[0-9]\\.[^\"]+\".*$")
|
||||
if(EXISTS "${GSS_INCLUDE_DIRS}/${_heimdal_manifest_file}")
|
||||
file(STRINGS "${GSS_INCLUDE_DIRS}/${_heimdal_manifest_file}" _heimdal_version_str
|
||||
REGEX "^.*version=\"[0-9]\\.[^\"]+\".*$")
|
||||
|
||||
string(REGEX MATCH "[0-9]\\.[^\"]+"
|
||||
GSS_VERSION "${heimdal_version_str}")
|
||||
string(REGEX MATCH "[0-9]\\.[^\"]+" GSS_VERSION "${_heimdal_version_str}")
|
||||
endif()
|
||||
|
||||
if(NOT GSS_VERSION)
|
||||
set(GSS_VERSION "Heimdal Unknown")
|
||||
endif()
|
||||
elseif(NOT GSS_VERSION AND GSS_FLAVOUR STREQUAL "MIT")
|
||||
get_filename_component(_MIT_VERSION "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos\\SDK\\CurrentVersion;VersionString]" NAME CACHE)
|
||||
if(WIN32 AND _MIT_VERSION)
|
||||
set(GSS_VERSION "${_MIT_VERSION}")
|
||||
get_filename_component(_mit_version "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos\\SDK\\CurrentVersion;VersionString]" NAME
|
||||
CACHE)
|
||||
if(WIN32 AND _mit_version)
|
||||
set(GSS_VERSION "${_mit_version}")
|
||||
else()
|
||||
set(GSS_VERSION "MIT Unknown")
|
||||
endif()
|
||||
@@ -297,16 +298,24 @@ if(GSS_FLAVOUR)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
set(_GSS_REQUIRED_VARS GSS_LIBRARIES GSS_FLAVOUR)
|
||||
|
||||
find_package_handle_standard_args(GSS
|
||||
REQUIRED_VARS
|
||||
${_GSS_REQUIRED_VARS}
|
||||
GSS_FLAVOUR
|
||||
GSS_LIBRARIES
|
||||
VERSION_VAR
|
||||
GSS_VERSION
|
||||
FAIL_MESSAGE
|
||||
"Could NOT find GSS, try to set the path to GSS root folder in the system variable GSS_ROOT_DIR"
|
||||
)
|
||||
|
||||
mark_as_advanced(GSS_INCLUDE_DIR GSS_LIBRARIES)
|
||||
mark_as_advanced(
|
||||
_GSS_CFLAGS
|
||||
_GSS_FOUND
|
||||
_GSS_INCLUDE_DIRS
|
||||
_GSS_LDFLAGS
|
||||
_GSS_LIBRARIES
|
||||
_GSS_LIBRARY_DIRS
|
||||
_GSS_MODULE_NAME
|
||||
_GSS_PREFIX
|
||||
_GSS_VERSION
|
||||
)
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
#***************************************************************************
|
||||
# _ _ ____ _
|
||||
# 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
|
||||
#
|
||||
###########################################################################
|
||||
# - Try to find the libssh2 library
|
||||
# Once done this will define
|
||||
#
|
||||
# LIBSSH2_FOUND - system has the libssh2 library
|
||||
# LIBSSH2_INCLUDE_DIR - the libssh2 include directory
|
||||
# LIBSSH2_LIBRARY - the libssh2 library name
|
||||
|
||||
find_path(LIBSSH2_INCLUDE_DIR libssh2.h)
|
||||
|
||||
find_library(LIBSSH2_LIBRARY NAMES ssh2 libssh2)
|
||||
|
||||
if(LIBSSH2_INCLUDE_DIR)
|
||||
file(STRINGS "${LIBSSH2_INCLUDE_DIR}/libssh2.h" libssh2_version_str REGEX "^#define[\t ]+LIBSSH2_VERSION[\t ]+\"(.*)\"")
|
||||
string(REGEX REPLACE "^.*\"([^\"]+)\"" "\\1" LIBSSH2_VERSION "${libssh2_version_str}")
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(LibSSH2
|
||||
REQUIRED_VARS LIBSSH2_LIBRARY LIBSSH2_INCLUDE_DIR
|
||||
VERSION_VAR LIBSSH2_VERSION)
|
||||
|
||||
mark_as_advanced(LIBSSH2_INCLUDE_DIR LIBSSH2_LIBRARY)
|
||||
@@ -0,0 +1,78 @@
|
||||
#***************************************************************************
|
||||
# _ _ ____ _
|
||||
# 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 libgsasl library
|
||||
#
|
||||
# Input variables:
|
||||
#
|
||||
# LIBGSASL_INCLUDE_DIR The libgsasl include directory
|
||||
# LIBGSASL_LIBRARY Path to libgsasl library
|
||||
#
|
||||
# Result variables:
|
||||
#
|
||||
# LIBGSASL_FOUND System has libgsasl
|
||||
# LIBGSASL_INCLUDE_DIRS The libgsasl include directories
|
||||
# LIBGSASL_LIBRARIES The libgsasl library names
|
||||
# LIBGSASL_LIBRARY_DIRS The libgsasl library directories
|
||||
# LIBGSASL_CFLAGS Required compiler flags
|
||||
# LIBGSASL_VERSION Version of 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")
|
||||
endif()
|
||||
|
||||
if(LIBGSASL_FOUND)
|
||||
string(REPLACE ";" " " LIBGSASL_CFLAGS "${LIBGSASL_CFLAGS}")
|
||||
message(STATUS "Found Libgsasl (via pkg-config): ${LIBGSASL_INCLUDE_DIRS} (found version \"${LIBGSASL_VERSION}\")")
|
||||
else()
|
||||
find_path(LIBGSASL_INCLUDE_DIR NAMES "gsasl.h")
|
||||
find_library(LIBGSASL_LIBRARY NAMES "gsasl" "libgsasl")
|
||||
|
||||
if(LIBGSASL_INCLUDE_DIR AND EXISTS "${LIBGSASL_INCLUDE_DIR}/gsasl-version.h")
|
||||
set(_version_regex "#[\t ]*define[\t ]+GSASL_VERSION[\t ]+\"([^\"]*)\"")
|
||||
file(STRINGS "${LIBGSASL_INCLUDE_DIR}/gsasl-version.h" _version_str REGEX "${_version_regex}")
|
||||
string(REGEX REPLACE "${_version_regex}" "\\1" _version_str "${_version_str}")
|
||||
set(LIBGSASL_VERSION "${_version_str}")
|
||||
unset(_version_regex)
|
||||
unset(_version_str)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Libgsasl
|
||||
REQUIRED_VARS
|
||||
LIBGSASL_INCLUDE_DIR
|
||||
LIBGSASL_LIBRARY
|
||||
VERSION_VAR
|
||||
LIBGSASL_VERSION
|
||||
)
|
||||
|
||||
if(LIBGSASL_FOUND)
|
||||
set(LIBGSASL_INCLUDE_DIRS ${LIBGSASL_INCLUDE_DIR})
|
||||
set(LIBGSASL_LIBRARIES ${LIBGSASL_LIBRARY})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(LIBGSASL_INCLUDE_DIR LIBGSASL_LIBRARY)
|
||||
endif()
|
||||
@@ -0,0 +1,78 @@
|
||||
#***************************************************************************
|
||||
# _ _ ____ _
|
||||
# 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 libidn2 library
|
||||
#
|
||||
# Input variables:
|
||||
#
|
||||
# LIBIDN2_INCLUDE_DIR The libidn2 include directory
|
||||
# LIBIDN2_LIBRARY Path to libidn2 library
|
||||
#
|
||||
# Result variables:
|
||||
#
|
||||
# LIBIDN2_FOUND System has libidn2
|
||||
# LIBIDN2_INCLUDE_DIRS The libidn2 include directories
|
||||
# LIBIDN2_LIBRARIES The libidn2 library names
|
||||
# LIBIDN2_LIBRARY_DIRS The libidn2 library directories
|
||||
# LIBIDN2_CFLAGS Required compiler flags
|
||||
# LIBIDN2_VERSION Version of 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")
|
||||
endif()
|
||||
|
||||
if(LIBIDN2_FOUND)
|
||||
string(REPLACE ";" " " LIBIDN2_CFLAGS "${LIBIDN2_CFLAGS}")
|
||||
message(STATUS "Found Libidn2 (via pkg-config): ${LIBIDN2_INCLUDE_DIRS} (found version \"${LIBIDN2_VERSION}\")")
|
||||
else()
|
||||
find_path(LIBIDN2_INCLUDE_DIR NAMES "idn2.h")
|
||||
find_library(LIBIDN2_LIBRARY NAMES "idn2" "libidn2")
|
||||
|
||||
if(LIBIDN2_INCLUDE_DIR AND EXISTS "${LIBIDN2_INCLUDE_DIR}/idn2.h")
|
||||
set(_version_regex "#[\t ]*define[\t ]+IDN2_VERSION[\t ]+\"([^\"]*)\"")
|
||||
file(STRINGS "${LIBIDN2_INCLUDE_DIR}/idn2.h" _version_str REGEX "${_version_regex}")
|
||||
string(REGEX REPLACE "${_version_regex}" "\\1" _version_str "${_version_str}")
|
||||
set(LIBIDN2_VERSION "${_version_str}")
|
||||
unset(_version_regex)
|
||||
unset(_version_str)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Libidn2
|
||||
REQUIRED_VARS
|
||||
LIBIDN2_INCLUDE_DIR
|
||||
LIBIDN2_LIBRARY
|
||||
VERSION_VAR
|
||||
LIBIDN2_VERSION
|
||||
)
|
||||
|
||||
if(LIBIDN2_FOUND)
|
||||
set(LIBIDN2_INCLUDE_DIRS ${LIBIDN2_INCLUDE_DIR})
|
||||
set(LIBIDN2_LIBRARIES ${LIBIDN2_LIBRARY})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(LIBIDN2_INCLUDE_DIR LIBIDN2_LIBRARY)
|
||||
endif()
|
||||
@@ -0,0 +1,80 @@
|
||||
#***************************************************************************
|
||||
# _ _ ____ _
|
||||
# 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 libpsl library
|
||||
#
|
||||
# Input variables:
|
||||
#
|
||||
# LIBPSL_INCLUDE_DIR The libpsl include directory
|
||||
# LIBPSL_LIBRARY Path to libpsl library
|
||||
#
|
||||
# Result variables:
|
||||
#
|
||||
# LIBPSL_FOUND System has libpsl
|
||||
# LIBPSL_INCLUDE_DIRS The libpsl include directories
|
||||
# LIBPSL_LIBRARIES The libpsl library names
|
||||
# LIBPSL_VERSION Version of libpsl
|
||||
|
||||
if(CURL_USE_PKGCONFIG)
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PC_LIBPSL "libpsl")
|
||||
endif()
|
||||
|
||||
find_path(LIBPSL_INCLUDE_DIR NAMES "libpsl.h"
|
||||
HINTS
|
||||
${PC_LIBPSL_INCLUDEDIR}
|
||||
${PC_LIBPSL_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
find_library(LIBPSL_LIBRARY NAMES "psl" "libpsl"
|
||||
HINTS
|
||||
${PC_LIBPSL_LIBDIR}
|
||||
${PC_LIBPSL_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
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)
|
||||
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)
|
||||
@@ -0,0 +1,92 @@
|
||||
#***************************************************************************
|
||||
# _ _ ____ _
|
||||
# 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 libssh library
|
||||
#
|
||||
# Input variables:
|
||||
#
|
||||
# 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
|
||||
|
||||
if(CURL_USE_PKGCONFIG AND
|
||||
NOT DEFINED LIBSSH_INCLUDE_DIR AND
|
||||
NOT DEFINED LIBSSH_LIBRARY)
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(LIBSSH "libssh")
|
||||
endif()
|
||||
|
||||
if(LIBSSH_FOUND)
|
||||
string(REPLACE ";" " " LIBSSH_CFLAGS "${LIBSSH_CFLAGS}")
|
||||
message(STATUS "Found Libssh (via pkg-config): ${LIBSSH_INCLUDE_DIRS} (found version \"${LIBSSH_VERSION}\")")
|
||||
else()
|
||||
find_path(LIBSSH_INCLUDE_DIR NAMES "libssh/libssh.h")
|
||||
find_library(LIBSSH_LIBRARY NAMES "ssh" "libssh")
|
||||
|
||||
if(LIBSSH_INCLUDE_DIR AND EXISTS "${LIBSSH_INCLUDE_DIR}/libssh/libssh_version.h")
|
||||
set(_version_regex1 "#[\t ]*define[\t ]+LIBSSH_VERSION_MAJOR[\t ]+([0-9]+).*")
|
||||
set(_version_regex2 "#[\t ]*define[\t ]+LIBSSH_VERSION_MINOR[\t ]+([0-9]+).*")
|
||||
set(_version_regex3 "#[\t ]*define[\t ]+LIBSSH_VERSION_MICRO[\t ]+([0-9]+).*")
|
||||
file(STRINGS "${LIBSSH_INCLUDE_DIR}/libssh/libssh_version.h" _version_str1 REGEX "${_version_regex1}")
|
||||
file(STRINGS "${LIBSSH_INCLUDE_DIR}/libssh/libssh_version.h" _version_str2 REGEX "${_version_regex2}")
|
||||
file(STRINGS "${LIBSSH_INCLUDE_DIR}/libssh/libssh_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(LIBSSH_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(Libssh
|
||||
REQUIRED_VARS
|
||||
LIBSSH_INCLUDE_DIR
|
||||
LIBSSH_LIBRARY
|
||||
VERSION_VAR
|
||||
LIBSSH_VERSION
|
||||
)
|
||||
|
||||
if(LIBSSH_FOUND)
|
||||
set(LIBSSH_INCLUDE_DIRS ${LIBSSH_INCLUDE_DIR})
|
||||
set(LIBSSH_LIBRARIES ${LIBSSH_LIBRARY})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(LIBSSH_INCLUDE_DIR LIBSSH_LIBRARY)
|
||||
endif()
|
||||
|
||||
if(LIBSSH_FOUND AND WIN32)
|
||||
list(APPEND LIBSSH_LIBRARIES "iphlpapi") # for if_nametoindex
|
||||
endif()
|
||||
@@ -0,0 +1,80 @@
|
||||
#***************************************************************************
|
||||
# _ _ ____ _
|
||||
# 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 libssh2 library
|
||||
#
|
||||
# Input variables:
|
||||
#
|
||||
# LIBSSH2_INCLUDE_DIR The libssh2 include directory
|
||||
# LIBSSH2_LIBRARY Path to libssh2 library
|
||||
#
|
||||
# Result variables:
|
||||
#
|
||||
# LIBSSH2_FOUND System has libssh2
|
||||
# LIBSSH2_INCLUDE_DIRS The libssh2 include directories
|
||||
# LIBSSH2_LIBRARIES The libssh2 library names
|
||||
# LIBSSH2_VERSION Version of libssh2
|
||||
|
||||
if(CURL_USE_PKGCONFIG)
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PC_LIBSSH2 "libssh2")
|
||||
endif()
|
||||
|
||||
find_path(LIBSSH2_INCLUDE_DIR NAMES "libssh2.h"
|
||||
HINTS
|
||||
${PC_LIBSSH2_INCLUDEDIR}
|
||||
${PC_LIBSSH2_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
find_library(LIBSSH2_LIBRARY NAMES "ssh2" "libssh2"
|
||||
HINTS
|
||||
${PC_LIBSSH2_LIBDIR}
|
||||
${PC_LIBSSH2_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
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)
|
||||
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)
|
||||
@@ -0,0 +1,88 @@
|
||||
#***************************************************************************
|
||||
# _ _ ____ _
|
||||
# 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 libuv library
|
||||
#
|
||||
# Input variables:
|
||||
#
|
||||
# LIBUV_INCLUDE_DIR The libuv include directory
|
||||
# LIBUV_LIBRARY Path to libuv library
|
||||
#
|
||||
# Result variables:
|
||||
#
|
||||
# LIBUV_FOUND System has libuv
|
||||
# LIBUV_INCLUDE_DIRS The libuv include directories
|
||||
# LIBUV_LIBRARIES The libuv library names
|
||||
# LIBUV_LIBRARY_DIRS The libuv library directories
|
||||
# LIBUV_CFLAGS Required compiler flags
|
||||
# LIBUV_VERSION Version of 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")
|
||||
endif()
|
||||
|
||||
if(LIBUV_FOUND)
|
||||
string(REPLACE ";" " " LIBUV_CFLAGS "${LIBUV_CFLAGS}")
|
||||
message(STATUS "Found Libuv (via pkg-config): ${LIBUV_INCLUDE_DIRS} (found version \"${LIBUV_VERSION}\")")
|
||||
else()
|
||||
find_path(LIBUV_INCLUDE_DIR NAMES "uv.h")
|
||||
find_library(LIBUV_LIBRARY NAMES "uv" "libuv")
|
||||
|
||||
if(LIBUV_INCLUDE_DIR AND EXISTS "${LIBUV_INCLUDE_DIR}/uv/version.h")
|
||||
set(_version_regex1 "#[\t ]*define[\t ]+UV_VERSION_MAJOR[\t ]+([0-9]+).*")
|
||||
set(_version_regex2 "#[\t ]*define[\t ]+UV_VERSION_MINOR[\t ]+([0-9]+).*")
|
||||
set(_version_regex3 "#[\t ]*define[\t ]+UV_VERSION_PATCH[\t ]+([0-9]+).*")
|
||||
file(STRINGS "${LIBUV_INCLUDE_DIR}/uv/version.h" _version_str1 REGEX "${_version_regex1}")
|
||||
file(STRINGS "${LIBUV_INCLUDE_DIR}/uv/version.h" _version_str2 REGEX "${_version_regex2}")
|
||||
file(STRINGS "${LIBUV_INCLUDE_DIR}/uv/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(LIBUV_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(Libuv
|
||||
REQUIRED_VARS
|
||||
LIBUV_INCLUDE_DIR
|
||||
LIBUV_LIBRARY
|
||||
VERSION_VAR
|
||||
LIBUV_VERSION
|
||||
)
|
||||
|
||||
if(LIBUV_FOUND)
|
||||
set(LIBUV_INCLUDE_DIRS ${LIBUV_INCLUDE_DIR})
|
||||
set(LIBUV_LIBRARIES ${LIBUV_LIBRARY})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(LIBUV_INCLUDE_DIR LIBUV_LIBRARY)
|
||||
endif()
|
||||
+26
-23
@@ -21,50 +21,53 @@
|
||||
# SPDX-License-Identifier: curl
|
||||
#
|
||||
###########################################################################
|
||||
# Find the msh3 library
|
||||
#
|
||||
# Input variables:
|
||||
#
|
||||
# MSH3_INCLUDE_DIR The msh3 include directory
|
||||
# MSH3_LIBRARY Path to msh3 library
|
||||
#
|
||||
# Result variables:
|
||||
#
|
||||
# MSH3_FOUND System has msh3
|
||||
# MSH3_INCLUDE_DIRS The msh3 include directories
|
||||
# MSH3_LIBRARIES The msh3 library names
|
||||
# MSH3_VERSION Version of msh3
|
||||
|
||||
#[=======================================================================[.rst:
|
||||
FindMSH3
|
||||
----------
|
||||
|
||||
Find the msh3 library
|
||||
|
||||
Result Variables
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
``MSH3_FOUND``
|
||||
System has msh3
|
||||
``MSH3_INCLUDE_DIRS``
|
||||
The msh3 include directories.
|
||||
``MSH3_LIBRARIES``
|
||||
The libraries needed to use msh3
|
||||
#]=======================================================================]
|
||||
if(UNIX)
|
||||
if(CURL_USE_PKGCONFIG)
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_search_module(PC_MSH3 libmsh3)
|
||||
pkg_check_modules(PC_MSH3 "libmsh3")
|
||||
endif()
|
||||
|
||||
find_path(MSH3_INCLUDE_DIR msh3.h
|
||||
find_path(MSH3_INCLUDE_DIR NAMES "msh3.h"
|
||||
HINTS
|
||||
${PC_MSH3_INCLUDEDIR}
|
||||
${PC_MSH3_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
find_library(MSH3_LIBRARY NAMES msh3
|
||||
find_library(MSH3_LIBRARY NAMES "msh3"
|
||||
HINTS
|
||||
${PC_MSH3_LIBDIR}
|
||||
${PC_MSH3_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
if(PC_MSH3_VERSION)
|
||||
set(MSH3_VERSION ${PC_MSH3_VERSION})
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(MSH3
|
||||
REQUIRED_VARS
|
||||
MSH3_LIBRARY
|
||||
MSH3_INCLUDE_DIR
|
||||
MSH3_LIBRARY
|
||||
VERSION_VAR
|
||||
MSH3_VERSION
|
||||
)
|
||||
|
||||
if(MSH3_FOUND)
|
||||
set(MSH3_LIBRARIES ${MSH3_LIBRARY})
|
||||
set(MSH3_INCLUDE_DIRS ${MSH3_INCLUDE_DIR})
|
||||
set(MSH3_LIBRARIES ${MSH3_LIBRARY})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(MSH3_INCLUDE_DIRS MSH3_LIBRARIES)
|
||||
mark_as_advanced(MSH3_INCLUDE_DIR MSH3_LIBRARY)
|
||||
|
||||
+83
-8
@@ -21,16 +21,91 @@
|
||||
# SPDX-License-Identifier: curl
|
||||
#
|
||||
###########################################################################
|
||||
find_path(MBEDTLS_INCLUDE_DIRS mbedtls/ssl.h)
|
||||
# Find the mbedtls library
|
||||
#
|
||||
# Input variables:
|
||||
#
|
||||
# MBEDTLS_INCLUDE_DIR The mbedtls include directory
|
||||
# MBEDTLS_INCLUDE_DIRS The mbedtls include directory (deprecated)
|
||||
# MBEDTLS_LIBRARY Path to mbedtls library
|
||||
# MBEDX509_LIBRARY Path to mbedx509 library
|
||||
# MBEDCRYPTO_LIBRARY Path to mbedcrypto library
|
||||
#
|
||||
# Result variables:
|
||||
#
|
||||
# MBEDTLS_FOUND System has mbedtls
|
||||
# MBEDTLS_INCLUDE_DIRS The mbedtls include directories
|
||||
# MBEDTLS_LIBRARIES The mbedtls library names
|
||||
# MBEDTLS_VERSION Version of mbedtls
|
||||
|
||||
find_library(MBEDTLS_LIBRARY mbedtls)
|
||||
find_library(MBEDX509_LIBRARY mbedx509)
|
||||
find_library(MBEDCRYPTO_LIBRARY mbedcrypto)
|
||||
if(DEFINED MBEDTLS_INCLUDE_DIRS AND NOT DEFINED MBEDTLS_INCLUDE_DIR)
|
||||
message(WARNING "MBEDTLS_INCLUDE_DIRS is deprecated, use MBEDTLS_INCLUDE_DIR instead.")
|
||||
set(MBEDTLS_INCLUDE_DIR "${MBEDTLS_INCLUDE_DIRS}")
|
||||
unset(MBEDTLS_INCLUDE_DIRS)
|
||||
endif()
|
||||
|
||||
set(MBEDTLS_LIBRARIES "${MBEDTLS_LIBRARY}" "${MBEDX509_LIBRARY}" "${MBEDCRYPTO_LIBRARY}")
|
||||
if(CURL_USE_PKGCONFIG)
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PC_MBEDTLS "mbedtls")
|
||||
endif()
|
||||
|
||||
find_path(MBEDTLS_INCLUDE_DIR NAMES "mbedtls/ssl.h"
|
||||
HINTS
|
||||
${PC_MBEDTLS_INCLUDEDIR}
|
||||
${PC_MBEDTLS_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
find_library(MBEDTLS_LIBRARY NAMES "mbedtls"
|
||||
HINTS
|
||||
${PC_MBEDTLS_LIBDIR}
|
||||
${PC_MBEDTLS_LIBRARY_DIRS}
|
||||
)
|
||||
find_library(MBEDX509_LIBRARY NAMES "mbedx509"
|
||||
HINTS
|
||||
${PC_MBEDTLS_LIBDIR}
|
||||
${PC_MBEDTLS_LIBRARY_DIRS}
|
||||
)
|
||||
find_library(MBEDCRYPTO_LIBRARY NAMES "mbedcrypto"
|
||||
HINTS
|
||||
${PC_MBEDTLS_LIBDIR}
|
||||
${PC_MBEDTLS_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
if(PC_MBEDTLS_VERSION)
|
||||
set(MBEDTLS_VERSION ${PC_MBEDTLS_VERSION})
|
||||
elseif(MBEDTLS_INCLUDE_DIR)
|
||||
if(EXISTS "${MBEDTLS_INCLUDE_DIR}/mbedtls/build_info.h") # 3.x
|
||||
set(_version_header "${MBEDTLS_INCLUDE_DIR}/mbedtls/build_info.h")
|
||||
elseif(EXISTS "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h") # 2.x
|
||||
set(_version_header "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h")
|
||||
else()
|
||||
unset(_version_header)
|
||||
endif()
|
||||
if(_version_header)
|
||||
set(_version_regex "#[\t ]*define[\t ]+MBEDTLS_VERSION_STRING[\t ]+\"([0-9.]+)\"")
|
||||
file(STRINGS "${_version_header}" _version_str REGEX "${_version_regex}")
|
||||
string(REGEX REPLACE "${_version_regex}" "\\1" _version_str "${_version_str}")
|
||||
set(MBEDTLS_VERSION "${_version_str}")
|
||||
unset(_version_regex)
|
||||
unset(_version_str)
|
||||
unset(_version_header)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(MbedTLS DEFAULT_MSG
|
||||
MBEDTLS_INCLUDE_DIRS MBEDTLS_LIBRARY MBEDX509_LIBRARY MBEDCRYPTO_LIBRARY)
|
||||
find_package_handle_standard_args(MbedTLS
|
||||
REQUIRED_VARS
|
||||
MBEDTLS_INCLUDE_DIR
|
||||
MBEDTLS_LIBRARY
|
||||
MBEDX509_LIBRARY
|
||||
MBEDCRYPTO_LIBRARY
|
||||
VERSION_VAR
|
||||
MBEDTLS_VERSION
|
||||
)
|
||||
|
||||
mark_as_advanced(MBEDTLS_INCLUDE_DIRS MBEDTLS_LIBRARY MBEDX509_LIBRARY MBEDCRYPTO_LIBRARY)
|
||||
if(MBEDTLS_FOUND)
|
||||
set(MBEDTLS_INCLUDE_DIRS ${MBEDTLS_INCLUDE_DIR})
|
||||
set(MBEDTLS_LIBRARIES ${MBEDTLS_LIBRARY} ${MBEDX509_LIBRARY} ${MBEDCRYPTO_LIBRARY})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(MBEDTLS_INCLUDE_DIR MBEDTLS_LIBRARY MBEDX509_LIBRARY MBEDCRYPTO_LIBRARY)
|
||||
|
||||
+52
-13
@@ -21,21 +21,60 @@
|
||||
# SPDX-License-Identifier: curl
|
||||
#
|
||||
###########################################################################
|
||||
include(FindPackageHandleStandardArgs)
|
||||
# Find the nghttp2 library
|
||||
#
|
||||
# Input variables:
|
||||
#
|
||||
# NGHTTP2_INCLUDE_DIR The nghttp2 include directory
|
||||
# NGHTTP2_LIBRARY Path to nghttp2 library
|
||||
#
|
||||
# Result variables:
|
||||
#
|
||||
# NGHTTP2_FOUND System has nghttp2
|
||||
# NGHTTP2_INCLUDE_DIRS The nghttp2 include directories
|
||||
# NGHTTP2_LIBRARIES The nghttp2 library names
|
||||
# NGHTTP2_VERSION Version of nghttp2
|
||||
|
||||
find_path(NGHTTP2_INCLUDE_DIR "nghttp2/nghttp2.h")
|
||||
if(CURL_USE_PKGCONFIG)
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PC_NGHTTP2 "libnghttp2")
|
||||
endif()
|
||||
|
||||
find_library(NGHTTP2_LIBRARY NAMES nghttp2 nghttp2_static)
|
||||
|
||||
find_package_handle_standard_args(NGHTTP2
|
||||
FOUND_VAR
|
||||
NGHTTP2_FOUND
|
||||
REQUIRED_VARS
|
||||
NGHTTP2_LIBRARY
|
||||
NGHTTP2_INCLUDE_DIR
|
||||
find_path(NGHTTP2_INCLUDE_DIR NAMES "nghttp2/nghttp2.h"
|
||||
HINTS
|
||||
${PC_NGHTTP2_INCLUDEDIR}
|
||||
${PC_NGHTTP2_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
set(NGHTTP2_INCLUDE_DIRS ${NGHTTP2_INCLUDE_DIR})
|
||||
set(NGHTTP2_LIBRARIES ${NGHTTP2_LIBRARY})
|
||||
find_library(NGHTTP2_LIBRARY NAMES "nghttp2" "nghttp2_static"
|
||||
HINTS
|
||||
${PC_NGHTTP2_LIBDIR}
|
||||
${PC_NGHTTP2_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
mark_as_advanced(NGHTTP2_INCLUDE_DIRS NGHTTP2_LIBRARIES)
|
||||
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()
|
||||
|
||||
mark_as_advanced(NGHTTP2_INCLUDE_DIR NGHTTP2_LIBRARY)
|
||||
|
||||
+29
-27
@@ -21,38 +21,32 @@
|
||||
# SPDX-License-Identifier: curl
|
||||
#
|
||||
###########################################################################
|
||||
# Find the nghttp3 library
|
||||
#
|
||||
# Input variables:
|
||||
#
|
||||
# NGHTTP3_INCLUDE_DIR The nghttp3 include directory
|
||||
# NGHTTP3_LIBRARY Path to nghttp3 library
|
||||
#
|
||||
# Result variables:
|
||||
#
|
||||
# NGHTTP3_FOUND System has nghttp3
|
||||
# NGHTTP3_INCLUDE_DIRS The nghttp3 include directories
|
||||
# NGHTTP3_LIBRARIES The nghttp3 library names
|
||||
# NGHTTP3_VERSION Version of nghttp3
|
||||
|
||||
#[=======================================================================[.rst:
|
||||
FindNGHTTP3
|
||||
----------
|
||||
|
||||
Find the nghttp3 library
|
||||
|
||||
Result Variables
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
``NGHTTP3_FOUND``
|
||||
System has nghttp3
|
||||
``NGHTTP3_INCLUDE_DIRS``
|
||||
The nghttp3 include directories.
|
||||
``NGHTTP3_LIBRARIES``
|
||||
The libraries needed to use nghttp3
|
||||
``NGHTTP3_VERSION``
|
||||
version of nghttp3.
|
||||
#]=======================================================================]
|
||||
|
||||
if(UNIX)
|
||||
if(CURL_USE_PKGCONFIG)
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_search_module(PC_NGHTTP3 libnghttp3)
|
||||
pkg_check_modules(PC_NGHTTP3 "libnghttp3")
|
||||
endif()
|
||||
|
||||
find_path(NGHTTP3_INCLUDE_DIR nghttp3/nghttp3.h
|
||||
find_path(NGHTTP3_INCLUDE_DIR NAMES "nghttp3/nghttp3.h"
|
||||
HINTS
|
||||
${PC_NGHTTP3_INCLUDEDIR}
|
||||
${PC_NGHTTP3_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
find_library(NGHTTP3_LIBRARY NAMES nghttp3
|
||||
find_library(NGHTTP3_LIBRARY NAMES "nghttp3"
|
||||
HINTS
|
||||
${PC_NGHTTP3_LIBDIR}
|
||||
${PC_NGHTTP3_LIBRARY_DIRS}
|
||||
@@ -60,19 +54,27 @@ find_library(NGHTTP3_LIBRARY NAMES nghttp3
|
||||
|
||||
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_LIBRARY
|
||||
NGHTTP3_INCLUDE_DIR
|
||||
VERSION_VAR NGHTTP3_VERSION
|
||||
NGHTTP3_LIBRARY
|
||||
VERSION_VAR
|
||||
NGHTTP3_VERSION
|
||||
)
|
||||
|
||||
if(NGHTTP3_FOUND)
|
||||
set(NGHTTP3_LIBRARIES ${NGHTTP3_LIBRARY})
|
||||
set(NGHTTP3_INCLUDE_DIRS ${NGHTTP3_INCLUDE_DIR})
|
||||
set(NGHTTP3_LIBRARIES ${NGHTTP3_LIBRARY})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(NGHTTP3_INCLUDE_DIRS NGHTTP3_LIBRARIES)
|
||||
mark_as_advanced(NGHTTP3_INCLUDE_DIR NGHTTP3_LIBRARY)
|
||||
|
||||
+48
-48
@@ -21,46 +21,40 @@
|
||||
# SPDX-License-Identifier: curl
|
||||
#
|
||||
###########################################################################
|
||||
# Find the ngtcp2 library
|
||||
#
|
||||
# This module accepts optional COMPONENTS to control the crypto library (these are
|
||||
# mutually exclusive):
|
||||
#
|
||||
# quictls: Use libngtcp2_crypto_quictls (choose this for LibreSSL)
|
||||
# BoringSSL: Use libngtcp2_crypto_boringssl (choose this for AWS-LC)
|
||||
# wolfSSL: Use libngtcp2_crypto_wolfssl
|
||||
# GnuTLS: Use libngtcp2_crypto_gnutls
|
||||
#
|
||||
# Input variables:
|
||||
#
|
||||
# NGTCP2_INCLUDE_DIR The ngtcp2 include directory
|
||||
# NGTCP2_LIBRARY Path to ngtcp2 library
|
||||
#
|
||||
# Result variables:
|
||||
#
|
||||
# NGTCP2_FOUND System has ngtcp2
|
||||
# NGTCP2_INCLUDE_DIRS The ngtcp2 include directories
|
||||
# NGTCP2_LIBRARIES The ngtcp2 library names
|
||||
# NGTCP2_VERSION Version of ngtcp2
|
||||
|
||||
#[=======================================================================[.rst:
|
||||
FindNGTCP2
|
||||
----------
|
||||
|
||||
Find the ngtcp2 library
|
||||
|
||||
This module accepts optional COMPONENTS to control the crypto library (these are
|
||||
mutually exclusive)::
|
||||
|
||||
quictls, LibreSSL: Use libngtcp2_crypto_quictls
|
||||
BoringSSL, AWS-LC: Use libngtcp2_crypto_boringssl
|
||||
wolfSSL: Use libngtcp2_crypto_wolfssl
|
||||
GnuTLS: Use libngtcp2_crypto_gnutls
|
||||
|
||||
Result Variables
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
``NGTCP2_FOUND``
|
||||
System has ngtcp2
|
||||
``NGTCP2_INCLUDE_DIRS``
|
||||
The ngtcp2 include directories.
|
||||
``NGTCP2_LIBRARIES``
|
||||
The libraries needed to use ngtcp2
|
||||
``NGTCP2_VERSION``
|
||||
version of ngtcp2.
|
||||
#]=======================================================================]
|
||||
|
||||
if(UNIX)
|
||||
if(CURL_USE_PKGCONFIG)
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_search_module(PC_NGTCP2 libngtcp2)
|
||||
pkg_check_modules(PC_NGTCP2 "libngtcp2")
|
||||
endif()
|
||||
|
||||
find_path(NGTCP2_INCLUDE_DIR ngtcp2/ngtcp2.h
|
||||
find_path(NGTCP2_INCLUDE_DIR NAMES "ngtcp2/ngtcp2.h"
|
||||
HINTS
|
||||
${PC_NGTCP2_INCLUDEDIR}
|
||||
${PC_NGTCP2_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
find_library(NGTCP2_LIBRARY NAMES ngtcp2
|
||||
find_library(NGTCP2_LIBRARY NAMES "ngtcp2"
|
||||
HINTS
|
||||
${PC_NGTCP2_LIBDIR}
|
||||
${PC_NGTCP2_LIBRARY_DIRS}
|
||||
@@ -68,33 +62,38 @@ find_library(NGTCP2_LIBRARY NAMES ngtcp2
|
||||
|
||||
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)
|
||||
if(component MATCHES "^(BoringSSL|quictls|wolfSSL|GnuTLS)")
|
||||
if(NGTCP2_CRYPTO_BACKEND)
|
||||
set(_ngtcp2_crypto_backend "")
|
||||
foreach(_component IN LISTS NGTCP2_FIND_COMPONENTS)
|
||||
if(_component MATCHES "^(BoringSSL|quictls|wolfSSL|GnuTLS)")
|
||||
if(_ngtcp2_crypto_backend)
|
||||
message(FATAL_ERROR "NGTCP2: Only one crypto library can be selected")
|
||||
endif()
|
||||
set(NGTCP2_CRYPTO_BACKEND ${component})
|
||||
set(_ngtcp2_crypto_backend ${_component})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(NGTCP2_CRYPTO_BACKEND)
|
||||
string(TOLOWER "ngtcp2_crypto_${NGTCP2_CRYPTO_BACKEND}" _crypto_library)
|
||||
if(UNIX)
|
||||
pkg_search_module(PC_${_crypto_library} lib${_crypto_library})
|
||||
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()
|
||||
find_library(${_crypto_library}_LIBRARY
|
||||
NAMES
|
||||
${_crypto_library}
|
||||
find_library(${_crypto_library}_LIBRARY NAMES ${_crypto_library}
|
||||
HINTS
|
||||
${PC_${_crypto_library}_LIBDIR}
|
||||
${PC_${_crypto_library}_LIBRARY_DIRS}
|
||||
)
|
||||
if(${_crypto_library}_LIBRARY)
|
||||
set(NGTCP2_${NGTCP2_CRYPTO_BACKEND}_FOUND TRUE)
|
||||
set(NGTCP2_${_ngtcp2_crypto_backend}_FOUND TRUE)
|
||||
set(NGTCP2_CRYPTO_LIBRARY ${${_crypto_library}_LIBRARY})
|
||||
endif()
|
||||
endif()
|
||||
@@ -103,15 +102,16 @@ endif()
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(NGTCP2
|
||||
REQUIRED_VARS
|
||||
NGTCP2_LIBRARY
|
||||
NGTCP2_INCLUDE_DIR
|
||||
VERSION_VAR NGTCP2_VERSION
|
||||
NGTCP2_LIBRARY
|
||||
VERSION_VAR
|
||||
NGTCP2_VERSION
|
||||
HANDLE_COMPONENTS
|
||||
)
|
||||
|
||||
if(NGTCP2_FOUND)
|
||||
set(NGTCP2_LIBRARIES ${NGTCP2_LIBRARY} ${NGTCP2_CRYPTO_LIBRARY})
|
||||
set(NGTCP2_INCLUDE_DIRS ${NGTCP2_INCLUDE_DIR})
|
||||
set(NGTCP2_LIBRARIES ${NGTCP2_LIBRARY} ${NGTCP2_CRYPTO_LIBRARY})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(NGTCP2_INCLUDE_DIRS NGTCP2_LIBRARIES)
|
||||
mark_as_advanced(NGTCP2_INCLUDE_DIR NGTCP2_LIBRARY NGTCP2_CRYPTO_LIBRARY)
|
||||
|
||||
+35
-27
@@ -21,50 +21,58 @@
|
||||
# SPDX-License-Identifier: curl
|
||||
#
|
||||
###########################################################################
|
||||
# - Try to find the nettle library
|
||||
# Once done this will define
|
||||
# Find the nettle library
|
||||
#
|
||||
# NETTLE_FOUND - system has nettle
|
||||
# NETTLE_INCLUDE_DIRS - nettle include directories
|
||||
# NETTLE_LIBRARIES - nettle library names
|
||||
# Input variables:
|
||||
#
|
||||
# NETTLE_INCLUDE_DIR The nettle include directory
|
||||
# NETTLE_LIBRARY Path to nettle library
|
||||
#
|
||||
# Result variables:
|
||||
#
|
||||
# NETTLE_FOUND System has nettle
|
||||
# NETTLE_INCLUDE_DIRS The nettle include directories
|
||||
# NETTLE_LIBRARIES The nettle library names
|
||||
# NETTLE_LIBRARY_DIRS The nettle library directories
|
||||
# NETTLE_CFLAGS Required compiler flags
|
||||
# NETTLE_VERSION Version of nettle
|
||||
|
||||
if(UNIX)
|
||||
if(CURL_USE_PKGCONFIG AND
|
||||
NOT DEFINED NETTLE_INCLUDE_DIR AND
|
||||
NOT DEFINED NETTLE_LIBRARY)
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(NETTLE "nettle")
|
||||
endif()
|
||||
|
||||
if(NETTLE_FOUND)
|
||||
set(NETTLE_LIBRARIES ${NETTLE_LINK_LIBRARIES})
|
||||
string(REPLACE ";" " " NETTLE_CFLAGS "${NETTLE_CFLAGS}")
|
||||
message(STATUS "Found Nettle (via pkg-config): ${NETTLE_INCLUDE_DIRS} (found version \"${NETTLE_VERSION}\")")
|
||||
else()
|
||||
find_path(NETTLE_INCLUDE_DIR NAMES "nettle/sha2.h")
|
||||
find_library(NETTLE_LIBRARY NAMES "nettle")
|
||||
|
||||
if(NETTLE_INCLUDE_DIR)
|
||||
if(EXISTS "${NETTLE_INCLUDE_DIR}/nettle/version.h")
|
||||
set(_version_regex_major "^#define[ \t]+NETTLE_VERSION_MAJOR[ \t]+([0-9]+).*")
|
||||
set(_version_regex_minor "^#define[ \t]+NETTLE_VERSION_MINOR[ \t]+([0-9]+).*")
|
||||
file(STRINGS "${NETTLE_INCLUDE_DIR}/nettle/version.h"
|
||||
_version_major REGEX "${_version_regex_major}")
|
||||
file(STRINGS "${NETTLE_INCLUDE_DIR}/nettle/version.h"
|
||||
_version_minor REGEX "${_version_regex_minor}")
|
||||
string(REGEX REPLACE "${_version_regex_major}" "\\1" _version_major "${_version_major}")
|
||||
string(REGEX REPLACE "${_version_regex_minor}" "\\1" _version_minor "${_version_minor}")
|
||||
unset(_version_regex_major)
|
||||
unset(_version_regex_minor)
|
||||
set(NETTLE_VERSION "${_version_major}.${_version_minor}")
|
||||
unset(_version_major)
|
||||
unset(_version_minor)
|
||||
else()
|
||||
set(NETTLE_VERSION "0.0")
|
||||
endif()
|
||||
if(NETTLE_INCLUDE_DIR AND EXISTS "${NETTLE_INCLUDE_DIR}/nettle/version.h")
|
||||
set(_version_regex1 "#[\t ]*define[ \t]+NETTLE_VERSION_MAJOR[ \t]+([0-9]+).*")
|
||||
set(_version_regex2 "#[\t ]*define[ \t]+NETTLE_VERSION_MINOR[ \t]+([0-9]+).*")
|
||||
file(STRINGS "${NETTLE_INCLUDE_DIR}/nettle/version.h" _version_str1 REGEX "${_version_regex1}")
|
||||
file(STRINGS "${NETTLE_INCLUDE_DIR}/nettle/version.h" _version_str2 REGEX "${_version_regex2}")
|
||||
string(REGEX REPLACE "${_version_regex1}" "\\1" _version_str1 "${_version_str1}")
|
||||
string(REGEX REPLACE "${_version_regex2}" "\\1" _version_str2 "${_version_str2}")
|
||||
set(NETTLE_VERSION "${_version_str1}.${_version_str2}")
|
||||
unset(_version_regex1)
|
||||
unset(_version_regex2)
|
||||
unset(_version_str1)
|
||||
unset(_version_str2)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args("nettle"
|
||||
find_package_handle_standard_args(Nettle
|
||||
REQUIRED_VARS
|
||||
NETTLE_INCLUDE_DIR
|
||||
NETTLE_LIBRARY
|
||||
VERSION_VAR NETTLE_VERSION)
|
||||
VERSION_VAR
|
||||
NETTLE_VERSION
|
||||
)
|
||||
|
||||
if(NETTLE_FOUND)
|
||||
set(NETTLE_INCLUDE_DIRS ${NETTLE_INCLUDE_DIR})
|
||||
|
||||
@@ -21,50 +21,53 @@
|
||||
# SPDX-License-Identifier: curl
|
||||
#
|
||||
###########################################################################
|
||||
# Find the quiche library
|
||||
#
|
||||
# Input variables:
|
||||
#
|
||||
# QUICHE_INCLUDE_DIR The quiche include directory
|
||||
# QUICHE_LIBRARY Path to quiche library
|
||||
#
|
||||
# Result variables:
|
||||
#
|
||||
# QUICHE_FOUND System has quiche
|
||||
# QUICHE_INCLUDE_DIRS The quiche include directories
|
||||
# QUICHE_LIBRARIES The quiche library names
|
||||
# QUICHE_VERSION Version of quiche
|
||||
|
||||
#[=======================================================================[.rst:
|
||||
FindQUICHE
|
||||
----------
|
||||
|
||||
Find the quiche library
|
||||
|
||||
Result Variables
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
``QUICHE_FOUND``
|
||||
System has quiche
|
||||
``QUICHE_INCLUDE_DIRS``
|
||||
The quiche include directories.
|
||||
``QUICHE_LIBRARIES``
|
||||
The libraries needed to use quiche
|
||||
#]=======================================================================]
|
||||
if(UNIX)
|
||||
if(CURL_USE_PKGCONFIG)
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_search_module(PC_QUICHE quiche)
|
||||
pkg_check_modules(PC_QUICHE "quiche")
|
||||
endif()
|
||||
|
||||
find_path(QUICHE_INCLUDE_DIR quiche.h
|
||||
find_path(QUICHE_INCLUDE_DIR NAMES "quiche.h"
|
||||
HINTS
|
||||
${PC_QUICHE_INCLUDEDIR}
|
||||
${PC_QUICHE_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
find_library(QUICHE_LIBRARY NAMES quiche
|
||||
find_library(QUICHE_LIBRARY NAMES "quiche"
|
||||
HINTS
|
||||
${PC_QUICHE_LIBDIR}
|
||||
${PC_QUICHE_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
if(PC_QUICHE_VERSION)
|
||||
set(QUICHE_VERSION ${PC_QUICHE_VERSION})
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(QUICHE
|
||||
find_package_handle_standard_args(Quiche
|
||||
REQUIRED_VARS
|
||||
QUICHE_LIBRARY
|
||||
QUICHE_INCLUDE_DIR
|
||||
QUICHE_LIBRARY
|
||||
VERSION_VAR
|
||||
QUICHE_VERSION
|
||||
)
|
||||
|
||||
if(QUICHE_FOUND)
|
||||
set(QUICHE_LIBRARIES ${QUICHE_LIBRARY})
|
||||
set(QUICHE_INCLUDE_DIRS ${QUICHE_INCLUDE_DIR})
|
||||
set(QUICHE_LIBRARIES ${QUICHE_LIBRARY})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(QUICHE_INCLUDE_DIRS QUICHE_LIBRARIES)
|
||||
mark_as_advanced(QUICHE_INCLUDE_DIR QUICHE_LIBRARY)
|
||||
@@ -21,25 +21,53 @@
|
||||
# SPDX-License-Identifier: curl
|
||||
#
|
||||
###########################################################################
|
||||
# - Try to find the libpsl library
|
||||
# Once done this will define
|
||||
# Find the rustls library
|
||||
#
|
||||
# LIBPSL_FOUND - system has the libpsl library
|
||||
# LIBPSL_INCLUDE_DIR - the libpsl include directory
|
||||
# LIBPSL_LIBRARY - the libpsl library name
|
||||
# Input variables:
|
||||
#
|
||||
# RUSTLS_INCLUDE_DIR The rustls include directory
|
||||
# RUSTLS_LIBRARY Path to rustls library
|
||||
#
|
||||
# Result variables:
|
||||
#
|
||||
# RUSTLS_FOUND System has rustls
|
||||
# RUSTLS_INCLUDE_DIRS The rustls include directories
|
||||
# RUSTLS_LIBRARIES The rustls library names
|
||||
# RUSTLS_VERSION Version of rustls
|
||||
|
||||
find_path(LIBPSL_INCLUDE_DIR libpsl.h)
|
||||
if(CURL_USE_PKGCONFIG)
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PC_RUSTLS "rustls")
|
||||
endif()
|
||||
|
||||
find_library(LIBPSL_LIBRARY NAMES psl libpsl)
|
||||
find_path(RUSTLS_INCLUDE_DIR NAMES "rustls.h"
|
||||
HINTS
|
||||
${PC_RUSTLS_INCLUDEDIR}
|
||||
${PC_RUSTLS_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
if(LIBPSL_INCLUDE_DIR)
|
||||
file(STRINGS "${LIBPSL_INCLUDE_DIR}/libpsl.h" libpsl_version_str REGEX "^#define[\t ]+PSL_VERSION[\t ]+\"(.*)\"")
|
||||
string(REGEX REPLACE "^.*\"([^\"]+)\"" "\\1" LIBPSL_VERSION "${libpsl_version_str}")
|
||||
find_library(RUSTLS_LIBRARY NAMES "rustls"
|
||||
HINTS
|
||||
${PC_RUSTLS_LIBDIR}
|
||||
${PC_RUSTLS_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
if(PC_RUSTLS_VERSION)
|
||||
set(RUSTLS_VERSION ${PC_RUSTLS_VERSION})
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(LibPSL
|
||||
REQUIRED_VARS LIBPSL_LIBRARY LIBPSL_INCLUDE_DIR
|
||||
VERSION_VAR LIBPSL_VERSION)
|
||||
find_package_handle_standard_args(Rustls
|
||||
REQUIRED_VARS
|
||||
RUSTLS_INCLUDE_DIR
|
||||
RUSTLS_LIBRARY
|
||||
VERSION_VAR
|
||||
RUSTLS_VERSION
|
||||
)
|
||||
|
||||
mark_as_advanced(LIBPSL_INCLUDE_DIR LIBPSL_LIBRARY)
|
||||
if(RUSTLS_FOUND)
|
||||
set(RUSTLS_INCLUDE_DIRS ${RUSTLS_INCLUDE_DIR})
|
||||
set(RUSTLS_LIBRARIES ${RUSTLS_LIBRARY})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(RUSTLS_INCLUDE_DIR RUSTLS_LIBRARY)
|
||||
@@ -0,0 +1,64 @@
|
||||
#***************************************************************************
|
||||
# _ _ ____ _
|
||||
# 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 wolfssh library
|
||||
#
|
||||
# Input variables:
|
||||
#
|
||||
# WOLFSSH_INCLUDE_DIR The wolfssh include directory
|
||||
# WOLFSSH_LIBRARY Path to wolfssh library
|
||||
#
|
||||
# Result variables:
|
||||
#
|
||||
# WOLFSSH_FOUND System has wolfssh
|
||||
# WOLFSSH_INCLUDE_DIRS The wolfssh include directories
|
||||
# WOLFSSH_LIBRARIES The wolfssh library names
|
||||
# WOLFSSH_VERSION Version of wolfssh
|
||||
|
||||
find_path(WOLFSSH_INCLUDE_DIR NAMES "wolfssh/ssh.h")
|
||||
find_library(WOLFSSH_LIBRARY NAMES "wolfssh" "libwolfssh")
|
||||
|
||||
if(WOLFSSH_INCLUDE_DIR AND EXISTS "${WOLFSSH_INCLUDE_DIR}/wolfssh/version.h")
|
||||
set(_version_regex "#[\t ]*define[\t ]+LIBWOLFSSH_VERSION_STRING[\t ]+\"([^\"]*)\"")
|
||||
file(STRINGS "${WOLFSSH_INCLUDE_DIR}/wolfssh/version.h" _version_str REGEX "${_version_regex}")
|
||||
string(REGEX REPLACE "${_version_regex}" "\\1" _version_str "${_version_str}")
|
||||
set(WOLFSSH_VERSION "${_version_str}")
|
||||
unset(_version_regex)
|
||||
unset(_version_str)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(WolfSSH
|
||||
REQUIRED_VARS
|
||||
WOLFSSH_INCLUDE_DIR
|
||||
WOLFSSH_LIBRARY
|
||||
VERSION_VAR
|
||||
WOLFSSH_VERSION
|
||||
)
|
||||
|
||||
if(WOLFSSH_FOUND)
|
||||
set(WOLFSSH_INCLUDE_DIRS ${WOLFSSH_INCLUDE_DIR})
|
||||
set(WOLFSSH_LIBRARIES ${WOLFSSH_LIBRARY})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(WOLFSSH_INCLUDE_DIR WOLFSSH_LIBRARY)
|
||||
+59
-21
@@ -21,40 +21,78 @@
|
||||
# SPDX-License-Identifier: curl
|
||||
#
|
||||
###########################################################################
|
||||
# Find the wolfssl library
|
||||
#
|
||||
# Input variables:
|
||||
#
|
||||
# WOLFSSL_INCLUDE_DIR The wolfssl include directory
|
||||
# WolfSSL_INCLUDE_DIR The wolfssl include directory (deprecated)
|
||||
# WOLFSSL_LIBRARY Path to wolfssl library
|
||||
# WolfSSL_LIBRARY Path to wolfssl library (deprecated)
|
||||
#
|
||||
# Result variables:
|
||||
#
|
||||
# WOLFSSL_FOUND System has wolfssl
|
||||
# WOLFSSL_INCLUDE_DIRS The wolfssl include directories
|
||||
# WOLFSSL_LIBRARIES The wolfssl library names
|
||||
# WOLFSSL_VERSION Version of wolfssl
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PC_WOLFSSL QUIET "wolfssl")
|
||||
if(DEFINED WolfSSL_INCLUDE_DIR AND NOT DEFINED WOLFSSL_INCLUDE_DIR)
|
||||
message(WARNING "WolfSSL_INCLUDE_DIR is deprecated, use WOLFSSL_INCLUDE_DIR instead.")
|
||||
set(WOLFSSL_INCLUDE_DIR "${WolfSSL_INCLUDE_DIR}")
|
||||
endif()
|
||||
if(DEFINED WolfSSL_LIBRARY AND NOT DEFINED WOLFSSL_LIBRARY)
|
||||
message(WARNING "WolfSSL_LIBRARY is deprecated, use WOLFSSL_LIBRARY instead.")
|
||||
set(WOLFSSL_LIBRARY "${WolfSSL_LIBRARY}")
|
||||
endif()
|
||||
|
||||
find_path(WolfSSL_INCLUDE_DIR
|
||||
NAMES "wolfssl/ssl.h"
|
||||
HINTS ${PC_WOLFSSL_INCLUDE_DIRS}
|
||||
if(CURL_USE_PKGCONFIG)
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PC_WOLFSSL "wolfssl")
|
||||
endif()
|
||||
|
||||
find_path(WOLFSSL_INCLUDE_DIR NAMES "wolfssl/ssl.h"
|
||||
HINTS
|
||||
${PC_WOLFSSL_INCLUDEDIR}
|
||||
${PC_WOLFSSL_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
find_library(WolfSSL_LIBRARY
|
||||
NAMES "wolfssl"
|
||||
HINTS ${PC_WOLFSSL_LIBRARY_DIRS}
|
||||
find_library(WOLFSSL_LIBRARY NAMES "wolfssl"
|
||||
HINTS
|
||||
${PC_WOLFSSL_LIBDIR}
|
||||
${PC_WOLFSSL_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
if(WolfSSL_INCLUDE_DIR)
|
||||
set(_version_regex "^#define[ \t]+LIBWOLFSSL_VERSION_STRING[ \t]+\"([^\"]+)\".*")
|
||||
file(STRINGS "${WolfSSL_INCLUDE_DIR}/wolfssl/version.h"
|
||||
WolfSSL_VERSION REGEX "${_version_regex}")
|
||||
string(REGEX REPLACE "${_version_regex}" "\\1"
|
||||
WolfSSL_VERSION "${WolfSSL_VERSION}")
|
||||
if(PC_WOLFSSL_VERSION)
|
||||
set(WOLFSSL_VERSION ${PC_WOLFSSL_VERSION})
|
||||
elseif(WOLFSSL_INCLUDE_DIR AND EXISTS "${WOLFSSL_INCLUDE_DIR}/wolfssl/version.h")
|
||||
set(_version_regex "#[\t ]*define[\t ]+LIBWOLFSSL_VERSION_STRING[\t ]+\"([^\"]*)\"")
|
||||
file(STRINGS "${WOLFSSL_INCLUDE_DIR}/wolfssl/version.h" _version_str REGEX "${_version_regex}")
|
||||
string(REGEX REPLACE "${_version_regex}" "\\1" _version_str "${_version_str}")
|
||||
set(WOLFSSL_VERSION "${_version_str}")
|
||||
unset(_version_regex)
|
||||
unset(_version_str)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(WolfSSL
|
||||
REQUIRED_VARS
|
||||
WolfSSL_INCLUDE_DIR
|
||||
WolfSSL_LIBRARY
|
||||
VERSION_VAR WolfSSL_VERSION
|
||||
WOLFSSL_INCLUDE_DIR
|
||||
WOLFSSL_LIBRARY
|
||||
VERSION_VAR
|
||||
WOLFSSL_VERSION
|
||||
)
|
||||
|
||||
if(WolfSSL_FOUND)
|
||||
set(WolfSSL_INCLUDE_DIRS ${WolfSSL_INCLUDE_DIR})
|
||||
set(WolfSSL_LIBRARIES ${WolfSSL_LIBRARY})
|
||||
if(WOLFSSL_FOUND)
|
||||
set(WOLFSSL_INCLUDE_DIRS ${WOLFSSL_INCLUDE_DIR})
|
||||
set(WOLFSSL_LIBRARIES ${WOLFSSL_LIBRARY})
|
||||
|
||||
if(NOT WIN32)
|
||||
find_library(_math_library "m")
|
||||
if(_math_library)
|
||||
list(APPEND WOLFSSL_LIBRARIES "m") # for log and pow
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
mark_as_advanced(WolfSSL_INCLUDE_DIR WolfSSL_LIBRARY)
|
||||
mark_as_advanced(WOLFSSL_INCLUDE_DIR WOLFSSL_LIBRARY)
|
||||
|
||||
+60
-37
@@ -21,58 +21,81 @@
|
||||
# SPDX-License-Identifier: curl
|
||||
#
|
||||
###########################################################################
|
||||
# Find the zstd library
|
||||
#
|
||||
# Input variables:
|
||||
#
|
||||
# ZSTD_INCLUDE_DIR The zstd include directory
|
||||
# Zstd_INCLUDE_DIR The zstd include directory (deprecated)
|
||||
# ZSTD_LIBRARY Path to zstd library
|
||||
# Zstd_LIBRARY Path to zstd library (deprecated)
|
||||
#
|
||||
# Result variables:
|
||||
#
|
||||
# ZSTD_FOUND System has zstd
|
||||
# ZSTD_INCLUDE_DIRS The zstd include directories
|
||||
# ZSTD_LIBRARIES The zstd library names
|
||||
# ZSTD_VERSION Version of zstd
|
||||
|
||||
#[=======================================================================[.rst:
|
||||
FindZstd
|
||||
----------
|
||||
|
||||
Find the zstd library
|
||||
|
||||
Result Variables
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
``Zstd_FOUND``
|
||||
System has zstd
|
||||
``Zstd_INCLUDE_DIRS``
|
||||
The zstd include directories.
|
||||
``Zstd_LIBRARIES``
|
||||
The libraries needed to use zstd
|
||||
#]=======================================================================]
|
||||
|
||||
if(UNIX)
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_search_module(PC_Zstd libzstd)
|
||||
if(DEFINED Zstd_INCLUDE_DIR AND NOT DEFINED ZSTD_INCLUDE_DIR)
|
||||
message(WARNING "Zstd_INCLUDE_DIR is deprecated, use ZSTD_INCLUDE_DIR instead.")
|
||||
set(ZSTD_INCLUDE_DIR "${Zstd_INCLUDE_DIR}")
|
||||
endif()
|
||||
if(DEFINED Zstd_LIBRARY AND NOT DEFINED ZSTD_LIBRARY)
|
||||
message(WARNING "Zstd_LIBRARY is deprecated, use ZSTD_LIBRARY instead.")
|
||||
set(ZSTD_LIBRARY "${Zstd_LIBRARY}")
|
||||
endif()
|
||||
|
||||
find_path(Zstd_INCLUDE_DIR zstd.h
|
||||
if(CURL_USE_PKGCONFIG)
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PC_ZSTD "libzstd")
|
||||
endif()
|
||||
|
||||
find_path(ZSTD_INCLUDE_DIR NAMES "zstd.h"
|
||||
HINTS
|
||||
${PC_Zstd_INCLUDEDIR}
|
||||
${PC_Zstd_INCLUDE_DIRS}
|
||||
${PC_ZSTD_INCLUDEDIR}
|
||||
${PC_ZSTD_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
find_library(Zstd_LIBRARY NAMES zstd
|
||||
find_library(ZSTD_LIBRARY NAMES "zstd"
|
||||
HINTS
|
||||
${PC_Zstd_LIBDIR}
|
||||
${PC_Zstd_LIBRARY_DIRS}
|
||||
${PC_ZSTD_LIBDIR}
|
||||
${PC_ZSTD_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
if(Zstd_INCLUDE_DIR)
|
||||
file(READ "${Zstd_INCLUDE_DIR}/zstd.h" _zstd_header)
|
||||
string(REGEX MATCH ".*define ZSTD_VERSION_MAJOR *([0-9]+).*define ZSTD_VERSION_MINOR *([0-9]+).*define ZSTD_VERSION_RELEASE *([0-9]+)" _zstd_ver "${_zstd_header}")
|
||||
set(Zstd_VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}")
|
||||
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_LIBRARY
|
||||
Zstd_INCLUDE_DIR
|
||||
VERSION_VAR Zstd_VERSION
|
||||
ZSTD_INCLUDE_DIR
|
||||
ZSTD_LIBRARY
|
||||
VERSION_VAR
|
||||
ZSTD_VERSION
|
||||
)
|
||||
|
||||
if(Zstd_FOUND)
|
||||
set(Zstd_LIBRARIES ${Zstd_LIBRARY})
|
||||
set(Zstd_INCLUDE_DIRS ${Zstd_INCLUDE_DIR})
|
||||
if(ZSTD_FOUND)
|
||||
set(ZSTD_INCLUDE_DIRS ${ZSTD_INCLUDE_DIR})
|
||||
set(ZSTD_LIBRARIES ${ZSTD_LIBRARY})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(Zstd_INCLUDE_DIRS Zstd_LIBRARIES)
|
||||
mark_as_advanced(ZSTD_INCLUDE_DIR ZSTD_LIBRARY)
|
||||
|
||||
+31
-35
@@ -21,60 +21,56 @@
|
||||
# SPDX-License-Identifier: curl
|
||||
#
|
||||
###########################################################################
|
||||
#File defines convenience macros for available feature testing
|
||||
# File defines convenience macros for available feature testing
|
||||
|
||||
# Check if header file exists and add it to the list.
|
||||
# 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)
|
||||
check_include_files("${CURL_INCLUDES};${FILE}" ${VARIABLE})
|
||||
if(${VARIABLE})
|
||||
set(CURL_INCLUDES ${CURL_INCLUDES} ${FILE})
|
||||
set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -D${VARIABLE}")
|
||||
macro(check_include_file_concat _file _variable)
|
||||
check_include_files("${CURL_INCLUDES};${_file}" ${_variable})
|
||||
if(${_variable})
|
||||
set(CURL_INCLUDES ${CURL_INCLUDES} ${_file})
|
||||
set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -D${_variable}")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# For other curl specific tests, use this macro.
|
||||
macro(curl_internal_test CURL_TEST)
|
||||
if(NOT DEFINED "${CURL_TEST}")
|
||||
set(MACRO_CHECK_FUNCTION_DEFINITIONS
|
||||
"-D${CURL_TEST} ${CURL_TEST_DEFINES} ${CMAKE_REQUIRED_FLAGS}")
|
||||
# Return result in variable: CURL_TEST_OUTPUT
|
||||
macro(curl_internal_test _curl_test)
|
||||
if(NOT DEFINED "${_curl_test}")
|
||||
set(_macro_check_function_definitions
|
||||
"-D${_curl_test} ${CURL_TEST_DEFINES} ${CMAKE_REQUIRED_FLAGS}")
|
||||
if(CMAKE_REQUIRED_LIBRARIES)
|
||||
set(CURL_TEST_ADD_LIBRARIES
|
||||
set(_curl_test_add_libraries
|
||||
"-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}")
|
||||
endif()
|
||||
|
||||
message(STATUS "Performing Test ${CURL_TEST}")
|
||||
try_compile(${CURL_TEST}
|
||||
message(STATUS "Performing Test ${_curl_test}")
|
||||
try_compile(${_curl_test}
|
||||
${CMAKE_BINARY_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CMake/CurlTests.c
|
||||
CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
|
||||
"${CURL_TEST_ADD_LIBRARIES}"
|
||||
OUTPUT_VARIABLE OUTPUT)
|
||||
if(${CURL_TEST})
|
||||
set(${CURL_TEST} 1 CACHE INTERNAL "Curl test ${FUNCTION}")
|
||||
message(STATUS "Performing Test ${CURL_TEST} - Success")
|
||||
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
|
||||
"Performing Test ${CURL_TEST} passed with the following output:\n"
|
||||
"${OUTPUT}\n")
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/CMake/CurlTests.c"
|
||||
CMAKE_FLAGS
|
||||
"-DCOMPILE_DEFINITIONS:STRING=${_macro_check_function_definitions}"
|
||||
"${_curl_test_add_libraries}"
|
||||
OUTPUT_VARIABLE CURL_TEST_OUTPUT)
|
||||
if(${_curl_test})
|
||||
set(${_curl_test} 1 CACHE INTERNAL "Curl test")
|
||||
message(STATUS "Performing Test ${_curl_test} - Success")
|
||||
else()
|
||||
message(STATUS "Performing Test ${CURL_TEST} - Failed")
|
||||
set(${CURL_TEST} "" CACHE INTERNAL "Curl test ${FUNCTION}")
|
||||
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
|
||||
"Performing Test ${CURL_TEST} failed with the following output:\n"
|
||||
"${OUTPUT}\n")
|
||||
set(${_curl_test} "" CACHE INTERNAL "Curl test")
|
||||
message(STATUS "Performing Test ${_curl_test} - Failed")
|
||||
endif()
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(optional_dependency 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(optional_dependency _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")
|
||||
|
||||
if(CURL_${DEPENDENCY} STREQUAL AUTO)
|
||||
find_package(${DEPENDENCY})
|
||||
elseif(CURL_${DEPENDENCY})
|
||||
find_package(${DEPENDENCY} REQUIRED)
|
||||
if(CURL_${_dependency} STREQUAL "AUTO")
|
||||
find_package(${_dependency})
|
||||
elseif(CURL_${_dependency})
|
||||
find_package(${_dependency} REQUIRED)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
+27
-31
@@ -25,17 +25,17 @@ include(CheckCSourceCompiles)
|
||||
include(CheckCSourceRuns)
|
||||
include(CheckTypeSize)
|
||||
|
||||
macro(add_header_include check header)
|
||||
if(${check})
|
||||
macro(add_header_include _check _header)
|
||||
if(${_check})
|
||||
set(_source_epilogue "${_source_epilogue}
|
||||
#include <${header}>")
|
||||
#include <${_header}>")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
|
||||
|
||||
if(NOT DEFINED HAVE_STRUCT_SOCKADDR_STORAGE)
|
||||
set(CMAKE_EXTRA_INCLUDE_FILES)
|
||||
unset(CMAKE_EXTRA_INCLUDE_FILES)
|
||||
if(WIN32)
|
||||
set(CMAKE_EXTRA_INCLUDE_FILES "winsock2.h")
|
||||
set(CMAKE_REQUIRED_DEFINITIONS "-DWIN32_LEAN_AND_MEAN")
|
||||
@@ -45,6 +45,7 @@ if(NOT DEFINED HAVE_STRUCT_SOCKADDR_STORAGE)
|
||||
endif()
|
||||
check_type_size("struct sockaddr_storage" SIZEOF_STRUCT_SOCKADDR_STORAGE)
|
||||
set(HAVE_STRUCT_SOCKADDR_STORAGE ${HAVE_SIZEOF_STRUCT_SOCKADDR_STORAGE})
|
||||
set(CMAKE_EXTRA_INCLUDE_FILES "")
|
||||
endif()
|
||||
|
||||
if(NOT WIN32)
|
||||
@@ -75,37 +76,32 @@ check_c_source_compiles("${_source_epilogue}
|
||||
|
||||
unset(CMAKE_TRY_COMPILE_TARGET_TYPE)
|
||||
|
||||
if(NOT CMAKE_CROSSCOMPILING AND NOT APPLE)
|
||||
if(NOT APPLE)
|
||||
set(_source_epilogue "#undef inline")
|
||||
add_header_include(HAVE_SYS_POLL_H "sys/poll.h")
|
||||
add_header_include(HAVE_POLL_H "poll.h")
|
||||
check_c_source_runs("${_source_epilogue}
|
||||
#include <stdlib.h>
|
||||
#include <sys/time.h>
|
||||
int main(void)
|
||||
{
|
||||
if(0 != poll(0, 0, 10)) {
|
||||
return 1; /* fail */
|
||||
}
|
||||
else {
|
||||
/* detect the 10.12 poll() breakage */
|
||||
struct timeval before, after;
|
||||
int rc;
|
||||
size_t us;
|
||||
|
||||
gettimeofday(&before, NULL);
|
||||
rc = poll(NULL, 0, 500);
|
||||
gettimeofday(&after, NULL);
|
||||
|
||||
us = (after.tv_sec - before.tv_sec) * 1000000 +
|
||||
(after.tv_usec - before.tv_usec);
|
||||
|
||||
if(us < 400000) {
|
||||
return 1;
|
||||
if(NOT CMAKE_CROSSCOMPILING)
|
||||
check_c_source_runs("${_source_epilogue}
|
||||
#include <stdlib.h>
|
||||
int main(void)
|
||||
{
|
||||
if(0 != poll(0, 0, 10)) {
|
||||
return 1; /* fail */
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}" HAVE_POLL_FINE)
|
||||
return 0;
|
||||
}" HAVE_POLL_FINE)
|
||||
elseif(UNIX)
|
||||
check_c_source_compiles("${_source_epilogue}
|
||||
#include <stdlib.h>
|
||||
int main(void)
|
||||
{
|
||||
#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L
|
||||
(void)poll(0, 0, 0);
|
||||
#else
|
||||
#error force compilation error
|
||||
#endif
|
||||
}" HAVE_POLL_FINE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Detect HAVE_GETADDRINFO_THREADSAFE
|
||||
|
||||
+13
-13
@@ -28,7 +28,7 @@ unset(WPICKY)
|
||||
if(CURL_WERROR AND
|
||||
((CMAKE_COMPILER_IS_GNUCC AND
|
||||
NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 5.0 AND
|
||||
NOT CMAKE_VERSION VERSION_LESS 3.23.0) OR # check_symbol_exists() incompatible with GCC -pedantic-errors in earlier CMake versions
|
||||
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"))
|
||||
set(WPICKY "${WPICKY} -pedantic-errors")
|
||||
endif()
|
||||
@@ -104,13 +104,13 @@ if(PICKY_COMPILER)
|
||||
-Wmissing-noreturn # clang 2.7 gcc 4.1
|
||||
-Wno-format-nonliteral # clang 1.0 gcc 2.96 (3.0)
|
||||
-Wno-system-headers # clang 1.0 gcc 3.0
|
||||
# -Wpadded # clang 2.9 gcc 4.1 # Not used because we cannot change public structs
|
||||
# -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 because this basically disallows default case
|
||||
# -Wswitch-enum # clang 2.7 gcc 4.1 # Not used: It basically disallows default case
|
||||
-Wtype-limits # clang 2.7 gcc 4.3
|
||||
-Wunreachable-code # clang 2.7 gcc 4.1
|
||||
# -Wunused-macros # clang 2.7 gcc 4.1 # Not practical
|
||||
@@ -160,7 +160,7 @@ if(PICKY_COMPILER)
|
||||
if((CMAKE_C_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 10.0) OR
|
||||
(CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 12.4))
|
||||
list(APPEND WPICKY_ENABLE
|
||||
-Wimplicit-fallthrough # clang 4.0 gcc 7.0 appleclang 12.4 # we have silencing markup for clang 10.0 and above only
|
||||
-Wimplicit-fallthrough # clang 4.0 gcc 7.0 appleclang 12.4 # We do silencing for clang 10.0 and above only
|
||||
)
|
||||
endif()
|
||||
else() # gcc
|
||||
@@ -180,7 +180,7 @@ if(PICKY_COMPILER)
|
||||
endif()
|
||||
if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.5 AND MINGW)
|
||||
list(APPEND WPICKY_ENABLE
|
||||
-Wno-pedantic-ms-format # gcc 4.5 (mingw-only)
|
||||
-Wno-pedantic-ms-format # gcc 4.5 (MinGW-only)
|
||||
)
|
||||
endif()
|
||||
if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.8)
|
||||
@@ -206,7 +206,7 @@ if(PICKY_COMPILER)
|
||||
list(APPEND WPICKY_ENABLE
|
||||
-Walloc-zero # gcc 7.0
|
||||
-Wduplicated-branches # gcc 7.0
|
||||
-Wformat-overflow=2 # gcc 7.0
|
||||
-Wno-format-overflow # gcc 7.0
|
||||
-Wformat-truncation=2 # gcc 7.0
|
||||
-Wimplicit-fallthrough # clang 4.0 gcc 7.0
|
||||
-Wrestrict # gcc 7.0
|
||||
@@ -221,20 +221,20 @@ if(PICKY_COMPILER)
|
||||
|
||||
#
|
||||
|
||||
foreach(_CCOPT IN LISTS WPICKY_ENABLE)
|
||||
set(WPICKY "${WPICKY} ${_CCOPT}")
|
||||
foreach(_ccopt IN LISTS WPICKY_ENABLE)
|
||||
set(WPICKY "${WPICKY} ${_ccopt}")
|
||||
endforeach()
|
||||
|
||||
foreach(_CCOPT IN LISTS WPICKY_DETECT)
|
||||
foreach(_ccopt IN LISTS WPICKY_DETECT)
|
||||
# surprisingly, CHECK_C_COMPILER_FLAG needs a new variable to store each new
|
||||
# test result in.
|
||||
string(MAKE_C_IDENTIFIER "OPT${_CCOPT}" _optvarname)
|
||||
string(MAKE_C_IDENTIFIER "OPT${_ccopt}" _optvarname)
|
||||
# GCC only warns about unknown -Wno- options if there are also other diagnostic messages,
|
||||
# so test for the positive form instead
|
||||
string(REPLACE "-Wno-" "-W" _CCOPT_ON "${_CCOPT}")
|
||||
check_c_compiler_flag(${_CCOPT_ON} ${_optvarname})
|
||||
string(REPLACE "-Wno-" "-W" _ccopt_on "${_ccopt}")
|
||||
check_c_compiler_flag(${_ccopt_on} ${_optvarname})
|
||||
if(${_optvarname})
|
||||
set(WPICKY "${WPICKY} ${_CCOPT}")
|
||||
set(WPICKY "${WPICKY} ${_ccopt}")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
@@ -41,6 +41,10 @@ if(MINGW)
|
||||
set(HAVE_SYS_PARAM_H 1)
|
||||
set(HAVE_SYS_TIME_H 1)
|
||||
set(HAVE_GETTIMEOFDAY 1)
|
||||
set(HAVE_STRINGS_H 1) # wrapper to string.h
|
||||
set(HAVE_UTIME_H 1) # wrapper to sys/utime.h
|
||||
set(HAVE_DIRENT_H 1)
|
||||
set(HAVE_OPENDIR 1)
|
||||
else()
|
||||
set(HAVE_LIBGEN_H 0)
|
||||
set(HAVE_STRCASECMP 0)
|
||||
@@ -48,6 +52,10 @@ else()
|
||||
set(HAVE_SYS_PARAM_H 0)
|
||||
set(HAVE_SYS_TIME_H 0)
|
||||
set(HAVE_GETTIMEOFDAY 0)
|
||||
set(HAVE_STRINGS_H 0)
|
||||
set(HAVE_UTIME_H 0)
|
||||
set(HAVE_DIRENT_H 0)
|
||||
set(HAVE_OPENDIR 0)
|
||||
if(MSVC)
|
||||
set(HAVE_UNISTD_H 0)
|
||||
set(HAVE_LOCALE_H 1)
|
||||
@@ -121,7 +129,6 @@ set(HAVE_IOCTL_SIOCGIFADDR 0)
|
||||
set(HAVE_POLL_H 0)
|
||||
set(HAVE_POLL_FINE 0)
|
||||
set(HAVE_PWD_H 0)
|
||||
set(HAVE_STRINGS_H 0) # mingw-w64 has it (wrapper to string.h)
|
||||
set(HAVE_SYS_EVENTFD_H 0)
|
||||
set(HAVE_SYS_FILIO_H 0)
|
||||
set(HAVE_SYS_WAIT_H 0)
|
||||
@@ -137,12 +144,9 @@ set(HAVE_SYS_UN_H 0)
|
||||
set(HAVE_SYS_UTIME_H 1)
|
||||
set(HAVE_TERMIOS_H 0)
|
||||
set(HAVE_TERMIO_H 0)
|
||||
set(HAVE_UTIME_H 0) # mingw-w64 has it (wrapper to sys/utime.h)
|
||||
set(HAVE_LINUX_TCP_H 0)
|
||||
|
||||
set(HAVE_DIRENT_H 0)
|
||||
set(HAVE_OPENDIR 0)
|
||||
|
||||
set(HAVE_FSEEKO 0)
|
||||
set(HAVE_FSEEKO 0) # mingw-w64 2.0.0 and newer has it
|
||||
set(HAVE__FSEEKI64 1)
|
||||
set(HAVE_SOCKET 1)
|
||||
set(HAVE_SELECT 1)
|
||||
@@ -161,7 +165,6 @@ set(HAVE_GMTIME_R 0)
|
||||
set(HAVE_GETHOSTBYNAME_R 0)
|
||||
set(HAVE_SIGNAL 1)
|
||||
set(HAVE_SIGACTION 0)
|
||||
set(HAVE_LINUX_TCP_H 0)
|
||||
set(HAVE_GLIBC_STRERROR_R 0)
|
||||
set(HAVE_MACH_ABSOLUTE_TIME 0)
|
||||
set(HAVE_GETIFADDRS 0)
|
||||
|
||||
@@ -24,12 +24,12 @@
|
||||
# File containing various utilities
|
||||
|
||||
# Returns number of arguments that evaluate to true
|
||||
function(count_true output_count_var)
|
||||
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")
|
||||
endif()
|
||||
endforeach()
|
||||
set(${output_count_var} ${lst_len} PARENT_SCOPE)
|
||||
set(${_output_count_var} ${lst_len} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
@@ -30,20 +30,20 @@ if(NOT DEFINED CMAKE_INSTALL_PREFIX)
|
||||
endif()
|
||||
message(${CMAKE_INSTALL_PREFIX})
|
||||
|
||||
file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
|
||||
string(REGEX REPLACE "\n" ";" files "${files}")
|
||||
foreach(file ${files})
|
||||
message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
|
||||
if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
||||
file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" _files)
|
||||
string(REGEX REPLACE "\n" ";" _files "${_files}")
|
||||
foreach(_file ${_files})
|
||||
message(STATUS "Uninstalling $ENV{DESTDIR}${_file}")
|
||||
if(IS_SYMLINK "$ENV{DESTDIR}${_file}" OR EXISTS "$ENV{DESTDIR}${_file}")
|
||||
exec_program(
|
||||
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
|
||||
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${_file}\""
|
||||
OUTPUT_VARIABLE rm_out
|
||||
RETURN_VALUE rm_retval
|
||||
)
|
||||
)
|
||||
if(NOT "${rm_retval}" STREQUAL 0)
|
||||
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
|
||||
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${_file}")
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
|
||||
message(STATUS "File $ENV{DESTDIR}${_file} does not exist.")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
@@ -23,6 +23,14 @@
|
||||
###########################################################################
|
||||
@PACKAGE_INIT@
|
||||
|
||||
if(NOT DEFINED CURL_USE_PKGCONFIG)
|
||||
if(UNIX OR (MSVC AND VCPKG_TOOLCHAIN)) # Keep in sync with root CMakeLists.txt
|
||||
set(CURL_USE_PKGCONFIG ON)
|
||||
else()
|
||||
set(CURL_USE_PKGCONFIG OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include(CMakeFindDependencyMacro)
|
||||
if(@USE_OPENSSL@)
|
||||
find_dependency(OpenSSL @OPENSSL_VERSION_MAJOR@)
|
||||
|
||||
+916
-715
@@ -24,11 +24,11 @@
|
||||
# by Tetetest and Sukender (Benoit Neil)
|
||||
|
||||
# Note: By default this CMake build script detects the version of some
|
||||
# dependencies using `check_symbol_exists`. Those checks do not work
|
||||
# in the case that both CURL and its dependency are included as
|
||||
# sub-projects in a larger build using `FetchContent`. To support
|
||||
# that case, additional variables may be defined by the parent
|
||||
# project, ideally in the "extra" find package redirect file:
|
||||
# dependencies using `check_symbol_exists`. Those checks do not work in
|
||||
# the case that both CURL and its dependency are included as sub-projects
|
||||
# in a larger build using `FetchContent`. To support that case, additional
|
||||
# variables may be defined by the parent project, ideally in the "extra"
|
||||
# find package redirect file:
|
||||
# https://cmake.org/cmake/help/latest/module/FetchContent.html#integrating-with-find-package
|
||||
#
|
||||
# The following variables are available:
|
||||
@@ -36,16 +36,33 @@
|
||||
# HAVE_OPENSSL_SRP: `SSL_CTX_set_srp_username` present in OpenSSL/wolfSSL
|
||||
# HAVE_GNUTLS_SRP: `gnutls_srp_verifier` present in GnuTLS
|
||||
# HAVE_SSL_CTX_SET_QUIC_METHOD: `SSL_CTX_set_quic_method` present in OpenSSL/wolfSSL
|
||||
# HAVE_QUICHE_CONN_SET_QLOG_FD: `quiche_conn_set_qlog_fd` present in QUICHE
|
||||
# HAVE_QUICHE_CONN_SET_QLOG_FD: `quiche_conn_set_qlog_fd` present in quiche
|
||||
# HAVE_ECH: ECH API checks for OpenSSL, BoringSSL or wolfSSL
|
||||
#
|
||||
# For each of the above variables, if the variable is DEFINED (either
|
||||
# to ON or OFF), the symbol detection will be skipped. If the
|
||||
# variable is NOT DEFINED, the symbol detection will be performed.
|
||||
# to ON or OFF), the symbol detection is skipped. If the variable is
|
||||
# NOT DEFINED, the symbol detection is performed.
|
||||
|
||||
cmake_minimum_required(VERSION 3.7...3.16 FATAL_ERROR)
|
||||
message(STATUS "Using CMake version ${CMAKE_VERSION}")
|
||||
|
||||
# Collect command-line arguments for buildinfo.txt.
|
||||
# Must reside at the top of the script to work as expected.
|
||||
get_cmake_property(_cache_vars CACHE_VARIABLES)
|
||||
unset(_cmake_args)
|
||||
foreach(_cache_var ${_cache_vars})
|
||||
get_property(_cache_var_helpstring CACHE ${_cache_var} PROPERTY HELPSTRING)
|
||||
if(_cache_var_helpstring STREQUAL "No help, variable specified on the command line.")
|
||||
get_property(_cache_var_type CACHE ${_cache_var} PROPERTY TYPE)
|
||||
if(_cache_var_type STREQUAL "UNINITIALIZED")
|
||||
set(_cache_var_type)
|
||||
else()
|
||||
set(_cache_var_type ":${_cache_var_type}")
|
||||
endif()
|
||||
set(_cmake_args "${_cmake_args} -D${_cache_var}${_cache_var_type}=\"${${_cache_var}}\"")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake;${CMAKE_MODULE_PATH}")
|
||||
include(Utilities)
|
||||
include(Macros)
|
||||
@@ -54,76 +71,140 @@ include(CheckCCompilerFlag)
|
||||
|
||||
project(CURL C)
|
||||
|
||||
file(STRINGS ${CURL_SOURCE_DIR}/include/curl/curlver.h CURL_VERSION_H_CONTENTS REGEX "#define LIBCURL_VERSION( |_NUM )")
|
||||
string(REGEX MATCH "#define LIBCURL_VERSION \"[^\"]*"
|
||||
CURL_VERSION ${CURL_VERSION_H_CONTENTS})
|
||||
unset(_target_flags)
|
||||
if(APPLE)
|
||||
set(_target_flags "${_target_flags} APPLE")
|
||||
endif()
|
||||
if(UNIX)
|
||||
set(_target_flags "${_target_flags} UNIX")
|
||||
endif()
|
||||
if(WIN32)
|
||||
set(_target_flags "${_target_flags} WIN32")
|
||||
endif()
|
||||
if(CYGWIN)
|
||||
set(_target_flags "${_target_flags} CYGWIN")
|
||||
endif()
|
||||
if(MSYS)
|
||||
set(_target_flags "${_target_flags} MSYS")
|
||||
endif()
|
||||
if(CMAKE_COMPILER_IS_GNUCC)
|
||||
set(_target_flags "${_target_flags} GCC")
|
||||
endif()
|
||||
if(MINGW)
|
||||
set(_target_flags "${_target_flags} MINGW")
|
||||
endif()
|
||||
if(MSVC)
|
||||
set(_target_flags "${_target_flags} MSVC")
|
||||
endif()
|
||||
if(VCPKG_TOOLCHAIN)
|
||||
set(_target_flags "${_target_flags} VCPKG")
|
||||
endif()
|
||||
if(CMAKE_CROSSCOMPILING)
|
||||
set(_target_flags "${_target_flags} CROSS")
|
||||
endif()
|
||||
message(STATUS "CMake platform flags:${_target_flags}")
|
||||
|
||||
if(CMAKE_CROSSCOMPILING)
|
||||
message(STATUS "Cross-compiling: "
|
||||
"${CMAKE_HOST_SYSTEM_NAME}/${CMAKE_HOST_SYSTEM_PROCESSOR} -> "
|
||||
"${CMAKE_SYSTEM_NAME}/${CMAKE_SYSTEM_PROCESSOR}")
|
||||
endif()
|
||||
|
||||
function(curl_dumpvars) # Dump all defined variables with their values
|
||||
message("::group::CMake Variable Dump")
|
||||
get_cmake_property(_vars VARIABLES)
|
||||
foreach(_var ${_vars})
|
||||
message("${_var} = ${${_var}}")
|
||||
endforeach()
|
||||
message("::endgroup::")
|
||||
endfunction()
|
||||
|
||||
file(STRINGS "${CURL_SOURCE_DIR}/include/curl/curlver.h" _curl_version_h_contents REGEX "#define LIBCURL_VERSION( |_NUM )")
|
||||
string(REGEX MATCH "#define LIBCURL_VERSION \"[^\"]*" CURL_VERSION ${_curl_version_h_contents})
|
||||
string(REGEX REPLACE "[^\"]+\"" "" CURL_VERSION ${CURL_VERSION})
|
||||
string(REGEX MATCH "#define LIBCURL_VERSION_NUM 0x[0-9a-fA-F]+"
|
||||
CURL_VERSION_NUM ${CURL_VERSION_H_CONTENTS})
|
||||
string(REGEX MATCH "#define LIBCURL_VERSION_NUM 0x[0-9a-fA-F]+" CURL_VERSION_NUM ${_curl_version_h_contents})
|
||||
string(REGEX REPLACE "[^0]+0x" "" CURL_VERSION_NUM ${CURL_VERSION_NUM})
|
||||
unset(_curl_version_h_contents)
|
||||
|
||||
|
||||
# Setup package meta-data
|
||||
# set(PACKAGE "curl")
|
||||
message(STATUS "curl version=[${CURL_VERSION}]")
|
||||
# set(PACKAGE_TARNAME "curl")
|
||||
# set(PACKAGE_NAME "curl")
|
||||
# set(PACKAGE_VERSION "-")
|
||||
# set(PACKAGE_STRING "curl-")
|
||||
# set(PACKAGE_BUGREPORT "a suitable curl mailing list => https://curl.se/mail/")
|
||||
set(OPERATING_SYSTEM "${CMAKE_SYSTEM_NAME}")
|
||||
|
||||
if(CMAKE_C_COMPILER_TARGET)
|
||||
set(OS "\"${CMAKE_C_COMPILER_TARGET}\"")
|
||||
else()
|
||||
set(OS "\"${CMAKE_SYSTEM_NAME}\"")
|
||||
endif()
|
||||
|
||||
include_directories(${CURL_SOURCE_DIR}/include)
|
||||
include_directories("${CURL_SOURCE_DIR}/include")
|
||||
|
||||
set(CMAKE_UNITY_BUILD_BATCH_SIZE 0)
|
||||
if(NOT DEFINED CMAKE_UNITY_BUILD_BATCH_SIZE)
|
||||
set(CMAKE_UNITY_BUILD_BATCH_SIZE 0)
|
||||
endif()
|
||||
|
||||
option(CURL_WERROR "Turn compiler warnings into errors" OFF)
|
||||
option(PICKY_COMPILER "Enable picky compiler options" ON)
|
||||
option(BUILD_CURL_EXE "Set to ON to build curl executable." ON)
|
||||
option(BUILD_CURL_EXE "Build curl executable" ON)
|
||||
option(BUILD_SHARED_LIBS "Build shared libraries" ON)
|
||||
option(BUILD_STATIC_LIBS "Build static libraries" OFF)
|
||||
option(BUILD_STATIC_CURL "Build curl executable with static libcurl" OFF)
|
||||
option(ENABLE_ARES "Set to ON to enable c-ares support" OFF)
|
||||
option(CURL_DISABLE_INSTALL "Set to ON to disable installation targets" OFF)
|
||||
option(ENABLE_ARES "Enable c-ares support" OFF)
|
||||
option(CURL_DISABLE_INSTALL "Disable installation targets" OFF)
|
||||
|
||||
if(WIN32)
|
||||
option(CURL_STATIC_CRT "Set to ON to build libcurl with static CRT on Windows (/MT)." OFF)
|
||||
option(ENABLE_UNICODE "Set to ON to use the Unicode version of the Windows API functions" OFF)
|
||||
set(CURL_TARGET_WINDOWS_VERSION "" CACHE STRING "Minimum target Windows version as hex string")
|
||||
if(CURL_TARGET_WINDOWS_VERSION)
|
||||
add_definitions(-D_WIN32_WINNT=${CURL_TARGET_WINDOWS_VERSION})
|
||||
list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_WIN32_WINNT=${CURL_TARGET_WINDOWS_VERSION})
|
||||
set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -D_WIN32_WINNT=${CURL_TARGET_WINDOWS_VERSION}")
|
||||
option(CURL_STATIC_CRT "Build libcurl with static CRT on Windows (/MT)" OFF)
|
||||
if(CURL_STATIC_CRT)
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MT")
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MTd")
|
||||
endif()
|
||||
|
||||
option(ENABLE_UNICODE "Use the Unicode version of the Windows API functions" OFF)
|
||||
if(ENABLE_UNICODE)
|
||||
add_definitions(-DUNICODE -D_UNICODE)
|
||||
add_definitions("-DUNICODE" "-D_UNICODE")
|
||||
if(MINGW)
|
||||
add_compile_options(-municode)
|
||||
add_compile_options("-municode")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
option(CURL_LTO "Turn on compiler Link Time Optimizations" OFF)
|
||||
|
||||
cmake_dependent_option(ENABLE_THREADED_RESOLVER "Set to ON to enable threaded DNS lookup"
|
||||
set(CURL_TARGET_WINDOWS_VERSION "" CACHE STRING "Minimum target Windows version as hex string")
|
||||
if(CURL_TARGET_WINDOWS_VERSION)
|
||||
add_definitions("-D_WIN32_WINNT=${CURL_TARGET_WINDOWS_VERSION}")
|
||||
list(APPEND CMAKE_REQUIRED_DEFINITIONS "-D_WIN32_WINNT=${CURL_TARGET_WINDOWS_VERSION}")
|
||||
set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -D_WIN32_WINNT=${CURL_TARGET_WINDOWS_VERSION}")
|
||||
endif()
|
||||
|
||||
# Detect actual value of _WIN32_WINNT and store as HAVE_WIN32_WINNT
|
||||
curl_internal_test(HAVE_WIN32_WINNT)
|
||||
if(HAVE_WIN32_WINNT)
|
||||
string(REGEX MATCH ".*_WIN32_WINNT=0x[0-9a-fA-F]+" CURL_TEST_OUTPUT "${CURL_TEST_OUTPUT}")
|
||||
string(REGEX REPLACE ".*_WIN32_WINNT=" "" CURL_TEST_OUTPUT "${CURL_TEST_OUTPUT}")
|
||||
string(REGEX REPLACE "0x([0-9a-f][0-9a-f][0-9a-f])$" "0x0\\1" CURL_TEST_OUTPUT "${CURL_TEST_OUTPUT}") # pad to 4 digits
|
||||
string(TOLOWER "${CURL_TEST_OUTPUT}" HAVE_WIN32_WINNT)
|
||||
message(STATUS "Found _WIN32_WINNT=${HAVE_WIN32_WINNT}")
|
||||
endif()
|
||||
# Avoid storing HAVE_WIN32_WINNT in CMake cache
|
||||
unset(HAVE_WIN32_WINNT CACHE)
|
||||
endif()
|
||||
option(CURL_LTO "Enable compiler Link Time Optimizations" OFF)
|
||||
|
||||
cmake_dependent_option(ENABLE_THREADED_RESOLVER "Enable threaded DNS lookup"
|
||||
ON "NOT ENABLE_ARES"
|
||||
OFF)
|
||||
|
||||
include(PickyWarnings)
|
||||
|
||||
option(ENABLE_DEBUG "Set to ON to enable curl debug features" OFF)
|
||||
option(ENABLE_CURLDEBUG "Set to ON to build with TrackMemory feature enabled" ${ENABLE_DEBUG})
|
||||
option(ENABLE_DEBUG "Enable curl debug features" OFF)
|
||||
option(ENABLE_CURLDEBUG "Enable TrackMemory feature" ${ENABLE_DEBUG})
|
||||
|
||||
if(MSVC)
|
||||
set(ENABLE_CURLDEBUG OFF) # FIXME: TrackMemory + MSVC fails test 558 and 1330. Tested with static build, Debug mode.
|
||||
endif()
|
||||
|
||||
if(ENABLE_DEBUG)
|
||||
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS DEBUGBUILD)
|
||||
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS "DEBUGBUILD")
|
||||
endif()
|
||||
|
||||
if(ENABLE_CURLDEBUG)
|
||||
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS CURLDEBUG)
|
||||
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS "CURLDEBUG")
|
||||
endif()
|
||||
|
||||
# For debug libs and exes, add "-d" postfix
|
||||
@@ -143,122 +224,141 @@ elseif(BUILD_STATIC_CURL AND NOT BUILD_STATIC_LIBS)
|
||||
set(BUILD_STATIC_CURL OFF)
|
||||
endif()
|
||||
|
||||
# lib flavour selected for curl tool
|
||||
# Lib flavour selected for curl tool
|
||||
if(BUILD_STATIC_CURL)
|
||||
set(LIB_SELECTED_FOR_EXE ${LIB_STATIC})
|
||||
else()
|
||||
set(LIB_SELECTED_FOR_EXE ${LIB_SHARED})
|
||||
endif()
|
||||
|
||||
# lib flavour selected for example and test programs.
|
||||
# Lib flavour selected for example and test programs.
|
||||
if(BUILD_SHARED_LIBS)
|
||||
set(LIB_SELECTED ${LIB_SHARED})
|
||||
else()
|
||||
set(LIB_SELECTED ${LIB_STATIC})
|
||||
endif()
|
||||
|
||||
# initialize CURL_LIBS
|
||||
# Override to force-disable or force-enable the use of pkg-config.
|
||||
if(UNIX OR (MSVC AND VCPKG_TOOLCHAIN)) # Keep in sync with CMake/curl-config.cmake.in
|
||||
set(_curl_use_pkgconfig_default ON)
|
||||
else()
|
||||
set(_curl_use_pkgconfig_default OFF)
|
||||
endif()
|
||||
option(CURL_USE_PKGCONFIG "Enable pkg-config to detect dependencies" ${_curl_use_pkgconfig_default})
|
||||
|
||||
# Initialize CURL_LIBS
|
||||
set(CURL_LIBS "")
|
||||
set(CURL_LIBDIRS "")
|
||||
set(LIBCURL_PC_REQUIRES_PRIVATE "")
|
||||
|
||||
if(ENABLE_ARES)
|
||||
set(USE_ARES 1)
|
||||
find_package(CARES REQUIRED)
|
||||
list(APPEND CURL_LIBS ${CARES_LIBRARY})
|
||||
find_package(Cares REQUIRED)
|
||||
list(APPEND CURL_LIBS ${CARES_LIBRARIES})
|
||||
list(APPEND LIBCURL_PC_REQUIRES_PRIVATE "libcares")
|
||||
add_definitions("-DCARES_NO_DEPRECATED") # Ignore c-ares deprecation warnings
|
||||
endif()
|
||||
|
||||
include(CurlSymbolHiding)
|
||||
|
||||
option(CURL_ENABLE_EXPORT_TARGET "to enable cmake export target" ON)
|
||||
option(CURL_ENABLE_EXPORT_TARGET "Enable CMake export target" ON)
|
||||
mark_as_advanced(CURL_ENABLE_EXPORT_TARGET)
|
||||
|
||||
option(CURL_DISABLE_ALTSVC "disables alt-svc support" OFF)
|
||||
option(CURL_DISABLE_ALTSVC "Disable alt-svc support" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_ALTSVC)
|
||||
option(CURL_DISABLE_SRP "disables TLS-SRP support" OFF)
|
||||
option(CURL_DISABLE_SRP "Disable TLS-SRP support" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_SRP)
|
||||
option(CURL_DISABLE_COOKIES "disables cookies support" OFF)
|
||||
option(CURL_DISABLE_COOKIES "Disable cookies support" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_COOKIES)
|
||||
option(CURL_DISABLE_BASIC_AUTH "disables Basic authentication" OFF)
|
||||
option(CURL_DISABLE_BASIC_AUTH "Disable Basic authentication" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_BASIC_AUTH)
|
||||
option(CURL_DISABLE_BEARER_AUTH "disables Bearer authentication" OFF)
|
||||
option(CURL_DISABLE_BEARER_AUTH "Disable Bearer authentication" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_BEARER_AUTH)
|
||||
option(CURL_DISABLE_DIGEST_AUTH "disables Digest authentication" OFF)
|
||||
option(CURL_DISABLE_DIGEST_AUTH "Disable Digest authentication" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_DIGEST_AUTH)
|
||||
option(CURL_DISABLE_KERBEROS_AUTH "disables Kerberos authentication" OFF)
|
||||
option(CURL_DISABLE_KERBEROS_AUTH "Disable Kerberos authentication" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_KERBEROS_AUTH)
|
||||
option(CURL_DISABLE_NEGOTIATE_AUTH "disables negotiate authentication" OFF)
|
||||
option(CURL_DISABLE_NEGOTIATE_AUTH "Disable negotiate authentication" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_NEGOTIATE_AUTH)
|
||||
option(CURL_DISABLE_AWS "disables AWS-SIG4" OFF)
|
||||
option(CURL_DISABLE_AWS "Disable AWS-SIG4" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_AWS)
|
||||
option(CURL_DISABLE_DICT "disables DICT" OFF)
|
||||
option(CURL_DISABLE_DICT "Disable DICT" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_DICT)
|
||||
option(CURL_DISABLE_DOH "disables DNS-over-HTTPS" OFF)
|
||||
option(CURL_DISABLE_DOH "Disable DNS-over-HTTPS" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_DOH)
|
||||
option(CURL_DISABLE_FILE "disables FILE" OFF)
|
||||
option(CURL_DISABLE_FILE "Disable FILE" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_FILE)
|
||||
cmake_dependent_option(CURL_DISABLE_FORM_API "disables form api" OFF
|
||||
"NOT CURL_DISABLE_MIME" ON)
|
||||
cmake_dependent_option(CURL_DISABLE_FORM_API "Disable form-api"
|
||||
OFF "NOT CURL_DISABLE_MIME"
|
||||
ON)
|
||||
mark_as_advanced(CURL_DISABLE_FORM_API)
|
||||
option(CURL_DISABLE_FTP "disables FTP" OFF)
|
||||
option(CURL_DISABLE_FTP "Disable FTP" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_FTP)
|
||||
option(CURL_DISABLE_GETOPTIONS "disables curl_easy_options API for existing options to curl_easy_setopt" OFF)
|
||||
option(CURL_DISABLE_GETOPTIONS "Disable curl_easy_options API for existing options to curl_easy_setopt" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_GETOPTIONS)
|
||||
option(CURL_DISABLE_GOPHER "disables Gopher" OFF)
|
||||
option(CURL_DISABLE_GOPHER "Disable Gopher" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_GOPHER)
|
||||
option(CURL_DISABLE_HEADERS_API "disables headers-api support" OFF)
|
||||
option(CURL_DISABLE_HEADERS_API "Disable headers-api support" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_HEADERS_API)
|
||||
option(CURL_DISABLE_HSTS "disables HSTS support" OFF)
|
||||
option(CURL_DISABLE_HSTS "Disable HSTS support" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_HSTS)
|
||||
option(CURL_DISABLE_HTTP "disables HTTP" OFF)
|
||||
option(CURL_DISABLE_HTTP "Disable HTTP" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_HTTP)
|
||||
option(CURL_DISABLE_HTTP_AUTH "disables all HTTP authentication methods" OFF)
|
||||
option(CURL_DISABLE_HTTP_AUTH "Disable all HTTP authentication methods" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_HTTP_AUTH)
|
||||
option(CURL_DISABLE_IMAP "disables IMAP" OFF)
|
||||
option(CURL_DISABLE_IMAP "Disable IMAP" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_IMAP)
|
||||
option(CURL_DISABLE_LDAP "disables LDAP" OFF)
|
||||
option(CURL_DISABLE_LDAP "Disable LDAP" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_LDAP)
|
||||
option(CURL_DISABLE_LDAPS "disables LDAPS" OFF)
|
||||
option(CURL_DISABLE_LDAPS "Disable LDAPS" ${CURL_DISABLE_LDAP})
|
||||
mark_as_advanced(CURL_DISABLE_LDAPS)
|
||||
option(CURL_DISABLE_LIBCURL_OPTION "disables --libcurl option from the curl tool" OFF)
|
||||
option(CURL_DISABLE_LIBCURL_OPTION "Disable --libcurl option from the curl tool" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_LIBCURL_OPTION)
|
||||
option(CURL_DISABLE_MIME "disables MIME support" OFF)
|
||||
option(CURL_DISABLE_MIME "Disable MIME support" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_MIME)
|
||||
option(CURL_DISABLE_MQTT "disables MQTT" OFF)
|
||||
option(CURL_DISABLE_MQTT "Disable MQTT" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_BINDLOCAL)
|
||||
option(CURL_DISABLE_BINDLOCAL "disables local binding support" OFF)
|
||||
option(CURL_DISABLE_BINDLOCAL "Disable local binding support" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_MQTT)
|
||||
option(CURL_DISABLE_NETRC "disables netrc parser" OFF)
|
||||
option(CURL_DISABLE_NETRC "Disable netrc parser" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_NETRC)
|
||||
option(CURL_DISABLE_NTLM "disables NTLM support" OFF)
|
||||
option(CURL_DISABLE_NTLM "Disable NTLM support" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_NTLM)
|
||||
option(CURL_DISABLE_PARSEDATE "disables date parsing" OFF)
|
||||
option(CURL_DISABLE_PARSEDATE "Disable date parsing" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_PARSEDATE)
|
||||
option(CURL_DISABLE_POP3 "disables POP3" OFF)
|
||||
option(CURL_DISABLE_POP3 "Disable POP3" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_POP3)
|
||||
option(CURL_DISABLE_PROGRESS_METER "disables built-in progress meter" OFF)
|
||||
option(CURL_DISABLE_PROGRESS_METER "Disable built-in progress meter" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_PROGRESS_METER)
|
||||
option(CURL_DISABLE_PROXY "disables proxy support" OFF)
|
||||
option(CURL_DISABLE_PROXY "Disable proxy support" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_PROXY)
|
||||
option(CURL_DISABLE_RTSP "disables RTSP" OFF)
|
||||
option(CURL_DISABLE_RTSP "Disable RTSP" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_SHA512_256)
|
||||
option(CURL_DISABLE_SHA512_256 "Disable SHA-512/256 hash algorithm" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_RTSP)
|
||||
option(CURL_DISABLE_SHUFFLE_DNS "disables shuffle DNS feature" OFF)
|
||||
option(CURL_DISABLE_SHUFFLE_DNS "Disable shuffle DNS feature" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_SHUFFLE_DNS)
|
||||
option(CURL_DISABLE_SMB "disables SMB" OFF)
|
||||
option(CURL_DISABLE_SMB "Disable SMB" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_SMB)
|
||||
option(CURL_DISABLE_SMTP "disables SMTP" OFF)
|
||||
option(CURL_DISABLE_SMTP "Disable SMTP" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_SMTP)
|
||||
option(CURL_DISABLE_SOCKETPAIR "disables use of socketpair for curl_multi_poll" OFF)
|
||||
option(CURL_DISABLE_SOCKETPAIR "Disable use of socketpair for curl_multi_poll" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_SOCKETPAIR)
|
||||
option(CURL_DISABLE_TELNET "disables Telnet" OFF)
|
||||
option(CURL_DISABLE_TELNET "Disable Telnet" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_TELNET)
|
||||
option(CURL_DISABLE_TFTP "disables TFTP" OFF)
|
||||
option(CURL_DISABLE_TFTP "Disable TFTP" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_TFTP)
|
||||
option(CURL_DISABLE_VERBOSE_STRINGS "disables verbose strings" OFF)
|
||||
option(CURL_DISABLE_VERBOSE_STRINGS "Disable verbose strings" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
|
||||
if(CURL_DISABLE_HTTP)
|
||||
set(CURL_DISABLE_RTSP ON)
|
||||
set(CURL_DISABLE_ALTSVC ON)
|
||||
set(CURL_DISABLE_HSTS ON)
|
||||
endif()
|
||||
|
||||
# Corresponds to HTTP_ONLY in lib/curl_setup.h
|
||||
option(HTTP_ONLY "disables all protocols except HTTP (This overrides all CURL_DISABLE_* options)" OFF)
|
||||
option(HTTP_ONLY "Disable all protocols except HTTP (This overrides all CURL_DISABLE_* options)" OFF)
|
||||
mark_as_advanced(HTTP_ONLY)
|
||||
|
||||
if(HTTP_ONLY)
|
||||
@@ -282,25 +382,25 @@ if(WINDOWS_STORE)
|
||||
set(CURL_DISABLE_TELNET ON) # telnet code needs fixing to compile for UWP.
|
||||
endif()
|
||||
|
||||
option(ENABLE_IPV6 "Define if you want to enable IPv6 support" ON)
|
||||
option(ENABLE_IPV6 "Enable IPv6 support" ON)
|
||||
mark_as_advanced(ENABLE_IPV6)
|
||||
if(ENABLE_IPV6 AND NOT WIN32)
|
||||
include(CheckStructHasMember)
|
||||
check_struct_has_member("struct sockaddr_in6" sin6_addr "netinet/in.h"
|
||||
check_struct_has_member("struct sockaddr_in6" "sin6_addr" "netinet/in.h"
|
||||
HAVE_SOCKADDR_IN6_SIN6_ADDR)
|
||||
check_struct_has_member("struct sockaddr_in6" sin6_scope_id "netinet/in.h"
|
||||
check_struct_has_member("struct sockaddr_in6" "sin6_scope_id" "netinet/in.h"
|
||||
HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
|
||||
if(NOT HAVE_SOCKADDR_IN6_SIN6_ADDR)
|
||||
message(WARNING "struct sockaddr_in6 not available, disabling IPv6 support")
|
||||
# Force the feature off as this name is used as guard macro...
|
||||
set(ENABLE_IPV6 OFF
|
||||
CACHE BOOL "Define if you want to enable IPv6 support" FORCE)
|
||||
set(ENABLE_IPV6 OFF CACHE BOOL "Enable IPv6 support" FORCE)
|
||||
endif()
|
||||
|
||||
if(APPLE AND NOT ENABLE_ARES)
|
||||
set(use_core_foundation_and_core_services ON)
|
||||
set(_use_core_foundation_and_core_services ON)
|
||||
|
||||
find_library(SYSTEMCONFIGURATION_FRAMEWORK "SystemConfiguration")
|
||||
mark_as_advanced(SYSTEMCONFIGURATION_FRAMEWORK)
|
||||
if(NOT SYSTEMCONFIGURATION_FRAMEWORK)
|
||||
message(FATAL_ERROR "SystemConfiguration framework not found")
|
||||
endif()
|
||||
@@ -314,9 +414,9 @@ endif()
|
||||
|
||||
find_package(Perl)
|
||||
|
||||
option(BUILD_LIBCURL_DOCS "to build libcurl man pages" ON)
|
||||
option(BUILD_MISC_DOCS "to build misc man pages (e.g. curl-config and mk-ca-bundle)" ON)
|
||||
option(ENABLE_CURL_MANUAL "to build the man page for curl and enable its -M/--manual option" ON)
|
||||
option(BUILD_LIBCURL_DOCS "Build libcurl man pages" ON)
|
||||
option(BUILD_MISC_DOCS "Build misc man pages (e.g. curl-config and mk-ca-bundle)" ON)
|
||||
option(ENABLE_CURL_MANUAL "Build the man page for curl and enable its -M/--manual option" ON)
|
||||
|
||||
if(ENABLE_CURL_MANUAL OR BUILD_LIBCURL_DOCS)
|
||||
if(PERL_FOUND)
|
||||
@@ -327,25 +427,19 @@ if(ENABLE_CURL_MANUAL OR BUILD_LIBCURL_DOCS)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CURL_STATIC_CRT)
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MT")
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MTd")
|
||||
endif()
|
||||
|
||||
# Disable warnings on Borland to avoid changing 3rd party code.
|
||||
if(BORLAND)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w-")
|
||||
endif()
|
||||
|
||||
# If we are on AIX, do the _ALL_SOURCE magic
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES AIX)
|
||||
set(_ALL_SOURCE 1)
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "AIX")
|
||||
add_definitions("-D_ALL_SOURCE")
|
||||
endif()
|
||||
|
||||
# If we are on Haiku, make sure that the network library is brought in.
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES Haiku)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -lnetwork")
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Haiku")
|
||||
list(APPEND CURL_LIBS "network")
|
||||
endif()
|
||||
|
||||
# Include all the necessary files for macros
|
||||
@@ -358,7 +452,7 @@ include(CheckSymbolExists)
|
||||
include(CheckTypeSize)
|
||||
include(CheckCSourceCompiles)
|
||||
|
||||
# On windows preload settings
|
||||
# Preload settings on Windows
|
||||
if(WIN32)
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/CMake/Platforms/WindowsCache.cmake)
|
||||
endif()
|
||||
@@ -370,7 +464,7 @@ if(ENABLE_THREADED_RESOLVER)
|
||||
find_package(Threads REQUIRED)
|
||||
set(USE_THREADS_POSIX ${CMAKE_USE_PTHREADS_INIT})
|
||||
set(HAVE_PTHREAD_H ${CMAKE_USE_PTHREADS_INIT})
|
||||
set(CURL_LIBS ${CURL_LIBS} ${CMAKE_THREAD_LIBS_INIT})
|
||||
list(APPEND CURL_LIBS ${CMAKE_THREAD_LIBS_INIT})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -380,17 +474,17 @@ if(HAVE_LIBSOCKET)
|
||||
set(CURL_LIBS "socket;${CURL_LIBS}")
|
||||
endif()
|
||||
|
||||
check_function_exists(gethostname HAVE_GETHOSTNAME)
|
||||
check_function_exists("gethostname" HAVE_GETHOSTNAME)
|
||||
|
||||
if(WIN32)
|
||||
list(APPEND CURL_LIBS "ws2_32" "bcrypt")
|
||||
endif()
|
||||
|
||||
# check SSL libraries
|
||||
# Check SSL libraries
|
||||
option(CURL_ENABLE_SSL "Enable SSL support" ON)
|
||||
|
||||
if(CURL_DEFAULT_SSL_BACKEND)
|
||||
set(valid_default_ssl_backend FALSE)
|
||||
set(_valid_default_ssl_backend FALSE)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
@@ -404,33 +498,43 @@ cmake_dependent_option(CURL_USE_MBEDTLS "Enable mbedTLS for SSL/TLS" OFF CURL_EN
|
||||
cmake_dependent_option(CURL_USE_BEARSSL "Enable BearSSL for SSL/TLS" OFF CURL_ENABLE_SSL OFF)
|
||||
cmake_dependent_option(CURL_USE_WOLFSSL "Enable wolfSSL for SSL/TLS" OFF CURL_ENABLE_SSL OFF)
|
||||
cmake_dependent_option(CURL_USE_GNUTLS "Enable GnuTLS for SSL/TLS" OFF CURL_ENABLE_SSL OFF)
|
||||
cmake_dependent_option(CURL_USE_RUSTLS "Enable Rustls for SSL/TLS" OFF CURL_ENABLE_SSL OFF)
|
||||
|
||||
set(openssl_default ON)
|
||||
set(_openssl_default ON)
|
||||
if(WIN32 OR CURL_USE_SECTRANSP OR CURL_USE_SCHANNEL OR CURL_USE_MBEDTLS OR CURL_USE_WOLFSSL)
|
||||
set(openssl_default OFF)
|
||||
set(_openssl_default OFF)
|
||||
endif()
|
||||
cmake_dependent_option(CURL_USE_OPENSSL "Enable OpenSSL for SSL/TLS" ${_openssl_default} CURL_ENABLE_SSL OFF)
|
||||
option(USE_OPENSSL_QUIC "Use OpenSSL and nghttp3 libraries for HTTP/3 support" OFF)
|
||||
if(USE_OPENSSL_QUIC AND NOT CURL_USE_OPENSSL)
|
||||
message(WARNING "OpenSSL QUIC has been requested, but without enabling OpenSSL. Will not enable QUIC.")
|
||||
set(USE_OPENSSL_QUIC OFF)
|
||||
endif()
|
||||
cmake_dependent_option(CURL_USE_OPENSSL "Enable OpenSSL for SSL/TLS" ${openssl_default} CURL_ENABLE_SSL OFF)
|
||||
option(CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG "Disable automatic loading of OpenSSL configuration" OFF)
|
||||
|
||||
count_true(enabled_ssl_options_count
|
||||
count_true(_enabled_ssl_options_count
|
||||
CURL_USE_SCHANNEL
|
||||
CURL_USE_SECTRANSP
|
||||
CURL_USE_OPENSSL
|
||||
CURL_USE_MBEDTLS
|
||||
CURL_USE_BEARSSL
|
||||
CURL_USE_WOLFSSL
|
||||
CURL_USE_GNUTLS
|
||||
CURL_USE_RUSTLS
|
||||
)
|
||||
if(enabled_ssl_options_count GREATER "1")
|
||||
if(_enabled_ssl_options_count GREATER 1)
|
||||
set(CURL_WITH_MULTI_SSL ON)
|
||||
elseif(_enabled_ssl_options_count EQUAL 0)
|
||||
set(CURL_DISABLE_HSTS ON)
|
||||
endif()
|
||||
|
||||
if(CURL_USE_SCHANNEL)
|
||||
set(SSL_ENABLED ON)
|
||||
set(_ssl_enabled ON)
|
||||
set(USE_SCHANNEL ON) # Windows native SSL/TLS support
|
||||
set(USE_WINDOWS_SSPI ON) # CURL_USE_SCHANNEL implies CURL_WINDOWS_SSPI
|
||||
|
||||
if(CURL_DEFAULT_SSL_BACKEND AND CURL_DEFAULT_SSL_BACKEND STREQUAL "schannel")
|
||||
set(valid_default_ssl_backend TRUE)
|
||||
set(_valid_default_ssl_backend TRUE)
|
||||
endif()
|
||||
endif()
|
||||
if(CURL_WINDOWS_SSPI)
|
||||
@@ -438,25 +542,30 @@ if(CURL_WINDOWS_SSPI)
|
||||
endif()
|
||||
|
||||
if(CURL_USE_SECTRANSP)
|
||||
set(use_core_foundation_and_core_services ON)
|
||||
set(_use_core_foundation_and_core_services ON)
|
||||
|
||||
find_library(SECURITY_FRAMEWORK "Security")
|
||||
mark_as_advanced(SECURITY_FRAMEWORK)
|
||||
if(NOT SECURITY_FRAMEWORK)
|
||||
message(FATAL_ERROR "Security framework not found")
|
||||
endif()
|
||||
|
||||
set(SSL_ENABLED ON)
|
||||
set(_ssl_enabled ON)
|
||||
set(USE_SECTRANSP ON)
|
||||
list(APPEND CURL_LIBS "-framework Security")
|
||||
|
||||
if(CURL_DEFAULT_SSL_BACKEND AND CURL_DEFAULT_SSL_BACKEND STREQUAL "secure-transport")
|
||||
set(valid_default_ssl_backend TRUE)
|
||||
set(_valid_default_ssl_backend TRUE)
|
||||
endif()
|
||||
|
||||
message(WARNING "Secure Transport does not support TLS 1.3.")
|
||||
endif()
|
||||
|
||||
if(use_core_foundation_and_core_services)
|
||||
if(_use_core_foundation_and_core_services)
|
||||
find_library(COREFOUNDATION_FRAMEWORK "CoreFoundation")
|
||||
mark_as_advanced(COREFOUNDATION_FRAMEWORK)
|
||||
find_library(CORESERVICES_FRAMEWORK "CoreServices")
|
||||
mark_as_advanced(CORESERVICES_FRAMEWORK)
|
||||
|
||||
if(NOT COREFOUNDATION_FRAMEWORK)
|
||||
message(FATAL_ERROR "CoreFoundation framework not found")
|
||||
@@ -470,99 +579,123 @@ endif()
|
||||
|
||||
if(CURL_USE_OPENSSL)
|
||||
find_package(OpenSSL REQUIRED)
|
||||
set(SSL_ENABLED ON)
|
||||
set(_ssl_enabled ON)
|
||||
set(USE_OPENSSL ON)
|
||||
|
||||
# Depend on OpenSSL via imported targets if supported by the running
|
||||
# version of CMake. This allows our dependents to get our dependencies
|
||||
# transitively.
|
||||
if(NOT CMAKE_VERSION VERSION_LESS 3.4)
|
||||
list(APPEND CURL_LIBS OpenSSL::SSL OpenSSL::Crypto)
|
||||
else()
|
||||
list(APPEND CURL_LIBS ${OPENSSL_LIBRARIES})
|
||||
include_directories(${OPENSSL_INCLUDE_DIR})
|
||||
endif()
|
||||
# Depend on OpenSSL via imported targets. This allows our dependents to
|
||||
# get our dependencies transitively.
|
||||
list(APPEND CURL_LIBS OpenSSL::SSL OpenSSL::Crypto)
|
||||
list(APPEND LIBCURL_PC_REQUIRES_PRIVATE "openssl")
|
||||
|
||||
if(CURL_DEFAULT_SSL_BACKEND AND CURL_DEFAULT_SSL_BACKEND STREQUAL "openssl")
|
||||
set(valid_default_ssl_backend TRUE)
|
||||
set(_valid_default_ssl_backend TRUE)
|
||||
endif()
|
||||
set(curl_ca_bundle_supported TRUE)
|
||||
set(_curl_ca_bundle_supported TRUE)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
if(NOT DEFINED HAVE_BORINGSSL)
|
||||
check_symbol_exists(OPENSSL_IS_BORINGSSL "openssl/base.h" HAVE_BORINGSSL)
|
||||
check_symbol_exists("OPENSSL_IS_BORINGSSL" "openssl/base.h" HAVE_BORINGSSL)
|
||||
endif()
|
||||
if(NOT DEFINED HAVE_AWSLC)
|
||||
check_symbol_exists(OPENSSL_IS_AWSLC "openssl/base.h" HAVE_AWSLC)
|
||||
check_symbol_exists("OPENSSL_IS_AWSLC" "openssl/base.h" HAVE_AWSLC)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CURL_USE_MBEDTLS)
|
||||
find_package(MbedTLS REQUIRED)
|
||||
set(SSL_ENABLED ON)
|
||||
set(_ssl_enabled ON)
|
||||
set(USE_MBEDTLS ON)
|
||||
list(APPEND CURL_LIBS ${MBEDTLS_LIBRARIES})
|
||||
list(APPEND LIBCURL_PC_REQUIRES_PRIVATE "mbedtls")
|
||||
include_directories(${MBEDTLS_INCLUDE_DIRS})
|
||||
|
||||
if(CURL_DEFAULT_SSL_BACKEND AND CURL_DEFAULT_SSL_BACKEND STREQUAL "mbedtls")
|
||||
set(valid_default_ssl_backend TRUE)
|
||||
set(_valid_default_ssl_backend TRUE)
|
||||
endif()
|
||||
set(curl_ca_bundle_supported TRUE)
|
||||
set(_curl_ca_bundle_supported TRUE)
|
||||
endif()
|
||||
|
||||
if(CURL_USE_BEARSSL)
|
||||
find_package(BearSSL REQUIRED)
|
||||
set(SSL_ENABLED ON)
|
||||
set(_ssl_enabled ON)
|
||||
set(USE_BEARSSL ON)
|
||||
list(APPEND CURL_LIBS ${BEARSSL_LIBRARY})
|
||||
list(APPEND CURL_LIBS ${BEARSSL_LIBRARIES})
|
||||
include_directories(${BEARSSL_INCLUDE_DIRS})
|
||||
|
||||
if(CURL_DEFAULT_SSL_BACKEND AND CURL_DEFAULT_SSL_BACKEND STREQUAL "bearssl")
|
||||
set(valid_default_ssl_backend TRUE)
|
||||
set(_valid_default_ssl_backend TRUE)
|
||||
endif()
|
||||
set(curl_ca_bundle_supported TRUE)
|
||||
set(_curl_ca_bundle_supported TRUE)
|
||||
|
||||
message(WARNING "BearSSL does not support TLS 1.3.")
|
||||
endif()
|
||||
|
||||
if(CURL_USE_WOLFSSL)
|
||||
find_package(WolfSSL REQUIRED)
|
||||
set(SSL_ENABLED ON)
|
||||
set(_ssl_enabled ON)
|
||||
set(USE_WOLFSSL ON)
|
||||
list(APPEND CURL_LIBS ${WolfSSL_LIBRARIES})
|
||||
list(APPEND CURL_LIBS ${WOLFSSL_LIBRARIES})
|
||||
list(APPEND LIBCURL_PC_REQUIRES_PRIVATE "wolfssl")
|
||||
include_directories(${WolfSSL_INCLUDE_DIRS})
|
||||
include_directories(${WOLFSSL_INCLUDE_DIRS})
|
||||
|
||||
if(CURL_DEFAULT_SSL_BACKEND AND CURL_DEFAULT_SSL_BACKEND STREQUAL "wolfssl")
|
||||
set(valid_default_ssl_backend TRUE)
|
||||
set(_valid_default_ssl_backend TRUE)
|
||||
endif()
|
||||
set(curl_ca_bundle_supported TRUE)
|
||||
set(_curl_ca_bundle_supported TRUE)
|
||||
endif()
|
||||
|
||||
if(CURL_USE_GNUTLS)
|
||||
find_package(GnuTLS REQUIRED)
|
||||
find_package(nettle REQUIRED)
|
||||
set(SSL_ENABLED ON)
|
||||
if(CURL_USE_PKGCONFIG)
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(GNUTLS "gnutls")
|
||||
if(GNUTLS_FOUND)
|
||||
set(GNUTLS_LIBRARIES ${GNUTLS_LINK_LIBRARIES})
|
||||
endif()
|
||||
endif()
|
||||
if(NOT GNUTLS_FOUND)
|
||||
find_package(GnuTLS REQUIRED)
|
||||
endif()
|
||||
find_package(Nettle REQUIRED)
|
||||
set(_ssl_enabled ON)
|
||||
set(USE_GNUTLS ON)
|
||||
list(APPEND CURL_LIBS ${GNUTLS_LIBRARIES} ${NETTLE_LIBRARIES})
|
||||
list(APPEND CURL_LIBDIRS ${NETTLE_LIBRARY_DIRS})
|
||||
list(APPEND LIBCURL_PC_REQUIRES_PRIVATE "gnutls" "nettle")
|
||||
include_directories(${GNUTLS_INCLUDE_DIRS} ${NETTLE_INCLUDE_DIRS})
|
||||
link_directories(${NETTLE_LIBRARY_DIRS})
|
||||
if(NETTLE_CFLAGS)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${NETTLE_CFLAGS}")
|
||||
endif()
|
||||
|
||||
if(CURL_DEFAULT_SSL_BACKEND AND CURL_DEFAULT_SSL_BACKEND STREQUAL "gnutls")
|
||||
set(valid_default_ssl_backend TRUE)
|
||||
set(_valid_default_ssl_backend TRUE)
|
||||
endif()
|
||||
set(curl_ca_bundle_supported TRUE)
|
||||
set(_curl_ca_bundle_supported TRUE)
|
||||
|
||||
if(NOT DEFINED HAVE_GNUTLS_SRP AND NOT CURL_DISABLE_SRP)
|
||||
cmake_push_check_state()
|
||||
set(CMAKE_REQUIRED_INCLUDES ${GNUTLS_INCLUDE_DIRS})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${GNUTLS_LIBRARIES})
|
||||
check_symbol_exists(gnutls_srp_verifier "gnutls/gnutls.h" HAVE_GNUTLS_SRP)
|
||||
check_symbol_exists("gnutls_srp_verifier" "gnutls/gnutls.h" HAVE_GNUTLS_SRP)
|
||||
cmake_pop_check_state()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CURL_DEFAULT_SSL_BACKEND AND NOT valid_default_ssl_backend)
|
||||
if(CURL_USE_RUSTLS)
|
||||
find_package(Rustls REQUIRED)
|
||||
set(_ssl_enabled ON)
|
||||
set(USE_RUSTLS ON)
|
||||
list(APPEND CURL_LIBS ${RUSTLS_LIBRARIES})
|
||||
list(APPEND LIBCURL_PC_REQUIRES_PRIVATE "rustls")
|
||||
include_directories(${RUSTLS_INCLUDE_DIRS})
|
||||
|
||||
if(CURL_DEFAULT_SSL_BACKEND AND CURL_DEFAULT_SSL_BACKEND STREQUAL "rustls")
|
||||
set(_valid_default_ssl_backend TRUE)
|
||||
endif()
|
||||
set(_curl_ca_bundle_supported TRUE)
|
||||
endif()
|
||||
|
||||
if(CURL_DEFAULT_SSL_BACKEND AND NOT _valid_default_ssl_backend)
|
||||
message(FATAL_ERROR "CURL_DEFAULT_SSL_BACKEND '${CURL_DEFAULT_SSL_BACKEND}' not enabled.")
|
||||
endif()
|
||||
|
||||
@@ -576,20 +709,14 @@ if(ZLIB_FOUND)
|
||||
set(HAVE_LIBZ ON)
|
||||
set(USE_ZLIB ON)
|
||||
|
||||
# Depend on ZLIB via imported targets if supported by the running
|
||||
# version of CMake. This allows our dependents to get our dependencies
|
||||
# transitively.
|
||||
if(NOT CMAKE_VERSION VERSION_LESS 3.4)
|
||||
list(APPEND CURL_LIBS ZLIB::ZLIB)
|
||||
else()
|
||||
list(APPEND CURL_LIBS ${ZLIB_LIBRARIES})
|
||||
include_directories(${ZLIB_INCLUDE_DIRS})
|
||||
endif()
|
||||
# Depend on ZLIB via imported targets. This allows our dependents to
|
||||
# get our dependencies transitively.
|
||||
list(APPEND CURL_LIBS ZLIB::ZLIB)
|
||||
list(APPEND LIBCURL_PC_REQUIRES_PRIVATE "zlib")
|
||||
list(APPEND CMAKE_REQUIRED_INCLUDES ${ZLIB_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
option(CURL_BROTLI "Set to ON to enable building curl with brotli support." OFF)
|
||||
option(CURL_BROTLI "Use brotli" OFF)
|
||||
set(HAVE_BROTLI OFF)
|
||||
if(CURL_BROTLI)
|
||||
find_package(Brotli REQUIRED)
|
||||
@@ -602,22 +729,22 @@ if(CURL_BROTLI)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(CURL_ZSTD "Set to ON to enable building curl with zstd support." OFF)
|
||||
option(CURL_ZSTD "Use zstd" OFF)
|
||||
set(HAVE_ZSTD OFF)
|
||||
if(CURL_ZSTD)
|
||||
find_package(Zstd REQUIRED)
|
||||
if(Zstd_FOUND AND NOT Zstd_VERSION VERSION_LESS "1.0.0")
|
||||
if(ZSTD_FOUND AND NOT ZSTD_VERSION VERSION_LESS 1.0.0)
|
||||
set(HAVE_ZSTD ON)
|
||||
list(APPEND CURL_LIBS ${Zstd_LIBRARIES})
|
||||
list(APPEND CURL_LIBS ${ZSTD_LIBRARIES})
|
||||
list(APPEND LIBCURL_PC_REQUIRES_PRIVATE "libzstd")
|
||||
include_directories(${Zstd_INCLUDE_DIRS})
|
||||
include_directories(${ZSTD_INCLUDE_DIRS})
|
||||
else()
|
||||
message(WARNING "zstd v1.0.0 or newer is required, disabling zstd support.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Check symbol in an OpenSSL-like TLS backend, or in EXTRA_LIBS depending on it.
|
||||
macro(openssl_check_symbol_exists SYMBOL FILES VARIABLE EXTRA_LIBS)
|
||||
# Check symbol in an OpenSSL-like TLS backend, or in _extra_libs depending on it.
|
||||
macro(openssl_check_symbol_exists _symbol _files _variable _extra_libs)
|
||||
cmake_push_check_state()
|
||||
if(USE_OPENSSL)
|
||||
set(CMAKE_REQUIRED_INCLUDES "${OPENSSL_INCLUDE_DIR}")
|
||||
@@ -630,8 +757,8 @@ macro(openssl_check_symbol_exists SYMBOL FILES VARIABLE EXTRA_LIBS)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES "bcrypt") # for OpenSSL/LibreSSL
|
||||
endif()
|
||||
elseif(USE_WOLFSSL)
|
||||
set(CMAKE_REQUIRED_INCLUDES "${WolfSSL_INCLUDE_DIRS}")
|
||||
set(CMAKE_REQUIRED_LIBRARIES "${WolfSSL_LIBRARIES}")
|
||||
set(CMAKE_REQUIRED_INCLUDES "${WOLFSSL_INCLUDE_DIRS}")
|
||||
set(CMAKE_REQUIRED_LIBRARIES "${WOLFSSL_LIBRARIES}")
|
||||
if(HAVE_LIBZ)
|
||||
list(APPEND CMAKE_REQUIRED_INCLUDES "${ZLIB_INCLUDE_DIRS}") # Public wolfSSL headers require zlib headers
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES "${ZLIB_LIBRARIES}")
|
||||
@@ -639,12 +766,10 @@ macro(openssl_check_symbol_exists SYMBOL FILES VARIABLE EXTRA_LIBS)
|
||||
if(WIN32)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES "ws2_32" "crypt32")
|
||||
endif()
|
||||
list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_UINTPTR_T) # to pull in stdint.h (as of wolfSSL v5.5.4)
|
||||
list(APPEND CMAKE_REQUIRED_DEFINITIONS "-DHAVE_UINTPTR_T") # to pull in stdint.h (as of wolfSSL v5.5.4)
|
||||
endif()
|
||||
if(NOT "${EXTRA_LIBS}" STREQUAL "")
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES "${EXTRA_LIBS}")
|
||||
endif()
|
||||
check_symbol_exists("${SYMBOL}" "${FILES}" "${VARIABLE}")
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES "${_extra_libs}")
|
||||
check_symbol_exists("${_symbol}" "${_files}" "${_variable}")
|
||||
cmake_pop_check_state()
|
||||
endmacro()
|
||||
|
||||
@@ -652,9 +777,10 @@ endmacro()
|
||||
macro(openssl_check_quic)
|
||||
if(NOT DEFINED HAVE_SSL_CTX_SET_QUIC_METHOD)
|
||||
if(USE_OPENSSL)
|
||||
openssl_check_symbol_exists(SSL_CTX_set_quic_method "openssl/ssl.h" HAVE_SSL_CTX_SET_QUIC_METHOD "")
|
||||
openssl_check_symbol_exists("SSL_CTX_set_quic_method" "openssl/ssl.h" HAVE_SSL_CTX_SET_QUIC_METHOD "")
|
||||
elseif(USE_WOLFSSL)
|
||||
openssl_check_symbol_exists(wolfSSL_set_quic_method "wolfssl/options.h;wolfssl/openssl/ssl.h" HAVE_SSL_CTX_SET_QUIC_METHOD "")
|
||||
openssl_check_symbol_exists("wolfSSL_set_quic_method" "wolfssl/options.h;wolfssl/openssl/ssl.h"
|
||||
HAVE_SSL_CTX_SET_QUIC_METHOD "")
|
||||
endif()
|
||||
endif()
|
||||
if(NOT HAVE_SSL_CTX_SET_QUIC_METHOD)
|
||||
@@ -663,16 +789,16 @@ macro(openssl_check_quic)
|
||||
endmacro()
|
||||
|
||||
if(USE_WOLFSSL)
|
||||
openssl_check_symbol_exists(wolfSSL_DES_ecb_encrypt "wolfssl/openssl/des.h" HAVE_WOLFSSL_DES_ECB_ENCRYPT "")
|
||||
openssl_check_symbol_exists(wolfSSL_BIO_set_shutdown "wolfssl/ssl.h" HAVE_WOLFSSL_FULL_BIO "")
|
||||
openssl_check_symbol_exists("wolfSSL_DES_ecb_encrypt" "wolfssl/openssl/des.h" HAVE_WOLFSSL_DES_ECB_ENCRYPT "")
|
||||
openssl_check_symbol_exists("wolfSSL_BIO_set_shutdown" "wolfssl/ssl.h" HAVE_WOLFSSL_FULL_BIO "")
|
||||
endif()
|
||||
|
||||
if(USE_OPENSSL OR USE_WOLFSSL)
|
||||
if(NOT DEFINED HAVE_SSL_SET0_WBIO)
|
||||
openssl_check_symbol_exists(SSL_set0_wbio "openssl/ssl.h" HAVE_SSL_SET0_WBIO "")
|
||||
openssl_check_symbol_exists("SSL_set0_wbio" "openssl/ssl.h" HAVE_SSL_SET0_WBIO "")
|
||||
endif()
|
||||
if(NOT DEFINED HAVE_OPENSSL_SRP AND NOT CURL_DISABLE_SRP)
|
||||
openssl_check_symbol_exists(SSL_CTX_set_srp_username "openssl/ssl.h" HAVE_OPENSSL_SRP "")
|
||||
openssl_check_symbol_exists("SSL_CTX_set_srp_username" "openssl/ssl.h" HAVE_OPENSSL_SRP "")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -683,11 +809,11 @@ if(USE_ECH)
|
||||
# Be sure that the TLS library actually supports ECH.
|
||||
if(NOT DEFINED HAVE_ECH)
|
||||
if(USE_OPENSSL AND HAVE_BORINGSSL)
|
||||
openssl_check_symbol_exists(SSL_set1_ech_config_list "openssl/ssl.h" HAVE_ECH "")
|
||||
openssl_check_symbol_exists("SSL_set1_ech_config_list" "openssl/ssl.h" HAVE_ECH "")
|
||||
elseif(USE_OPENSSL)
|
||||
openssl_check_symbol_exists(SSL_ech_set1_echconfig "openssl/ech.h" HAVE_ECH "")
|
||||
openssl_check_symbol_exists("SSL_ech_set1_echconfig" "openssl/ech.h" HAVE_ECH "")
|
||||
elseif(USE_WOLFSSL)
|
||||
openssl_check_symbol_exists(wolfSSL_CTX_GenerateEchConfig "wolfssl/options.h;wolfssl/ssl.h" HAVE_ECH "")
|
||||
openssl_check_symbol_exists("wolfSSL_CTX_GenerateEchConfig" "wolfssl/options.h;wolfssl/ssl.h" HAVE_ECH "")
|
||||
endif()
|
||||
endif()
|
||||
if(NOT HAVE_ECH)
|
||||
@@ -700,30 +826,34 @@ if(USE_ECH)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(USE_NGHTTP2 "Use nghttp2 library" OFF)
|
||||
option(USE_NGHTTP2 "Use nghttp2 library" ON)
|
||||
if(USE_NGHTTP2)
|
||||
find_package(NGHTTP2 REQUIRED)
|
||||
include_directories(${NGHTTP2_INCLUDE_DIRS})
|
||||
list(APPEND CURL_LIBS ${NGHTTP2_LIBRARIES})
|
||||
list(APPEND LIBCURL_PC_REQUIRES_PRIVATE "libnghttp2")
|
||||
find_package(NGHTTP2)
|
||||
if(NGHTTP2_FOUND)
|
||||
include_directories(${NGHTTP2_INCLUDE_DIRS})
|
||||
list(APPEND CURL_LIBS ${NGHTTP2_LIBRARIES})
|
||||
list(APPEND LIBCURL_PC_REQUIRES_PRIVATE "libnghttp2")
|
||||
else()
|
||||
set(USE_NGHTTP2 OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(USE_NGTCP2 "Use ngtcp2 and nghttp3 libraries for HTTP/3 support" OFF)
|
||||
if(USE_NGTCP2)
|
||||
if(USE_OPENSSL OR USE_WOLFSSL)
|
||||
if(USE_WOLFSSL)
|
||||
find_package(NGTCP2 REQUIRED wolfSSL)
|
||||
find_package(NGTCP2 REQUIRED "wolfSSL")
|
||||
list(APPEND LIBCURL_PC_REQUIRES_PRIVATE "libngtcp2_crypto_wolfssl")
|
||||
elseif(HAVE_BORINGSSL OR HAVE_AWSLC)
|
||||
find_package(NGTCP2 REQUIRED BoringSSL)
|
||||
find_package(NGTCP2 REQUIRED "BoringSSL")
|
||||
list(APPEND LIBCURL_PC_REQUIRES_PRIVATE "libngtcp2_crypto_boringssl")
|
||||
else()
|
||||
find_package(NGTCP2 REQUIRED quictls)
|
||||
find_package(NGTCP2 REQUIRED "quictls")
|
||||
list(APPEND LIBCURL_PC_REQUIRES_PRIVATE "libngtcp2_crypto_quictls")
|
||||
endif()
|
||||
openssl_check_quic()
|
||||
elseif(USE_GNUTLS)
|
||||
find_package(NGTCP2 REQUIRED GnuTLS)
|
||||
find_package(NGTCP2 REQUIRED "GnuTLS")
|
||||
list(APPEND LIBCURL_PC_REQUIRES_PRIVATE "libngtcp2_crypto_gnutls")
|
||||
else()
|
||||
message(FATAL_ERROR "ngtcp2 requires OpenSSL, wolfSSL or GnuTLS")
|
||||
@@ -745,7 +875,7 @@ if(USE_QUICHE)
|
||||
if(USE_NGTCP2)
|
||||
message(FATAL_ERROR "Only one HTTP/3 backend can be selected!")
|
||||
endif()
|
||||
find_package(QUICHE REQUIRED)
|
||||
find_package(Quiche REQUIRED)
|
||||
if(NOT HAVE_BORINGSSL)
|
||||
message(FATAL_ERROR "quiche requires BoringSSL")
|
||||
endif()
|
||||
@@ -758,7 +888,7 @@ if(USE_QUICHE)
|
||||
cmake_push_check_state()
|
||||
set(CMAKE_REQUIRED_INCLUDES "${QUICHE_INCLUDE_DIRS}")
|
||||
set(CMAKE_REQUIRED_LIBRARIES "${QUICHE_LIBRARIES}")
|
||||
check_symbol_exists(quiche_conn_set_qlog_fd "quiche.h" HAVE_QUICHE_CONN_SET_QLOG_FD)
|
||||
check_symbol_exists("quiche_conn_set_qlog_fd" "quiche.h" HAVE_QUICHE_CONN_SET_QLOG_FD)
|
||||
cmake_pop_check_state()
|
||||
endif()
|
||||
endif()
|
||||
@@ -768,13 +898,13 @@ if(USE_MSH3)
|
||||
if(USE_NGTCP2 OR USE_QUICHE)
|
||||
message(FATAL_ERROR "Only one HTTP/3 backend can be selected!")
|
||||
endif()
|
||||
find_package(MSH3 REQUIRED)
|
||||
set(USE_MSH3 ON)
|
||||
include_directories(${MSH3_INCLUDE_DIRS})
|
||||
list(APPEND CURL_LIBS ${MSH3_LIBRARIES})
|
||||
list(APPEND LIBCURL_PC_REQUIRES_PRIVATE "libmsh3")
|
||||
endif()
|
||||
|
||||
option(USE_OPENSSL_QUIC "Use openssl and nghttp3 libraries for HTTP/3 support" OFF)
|
||||
if(USE_OPENSSL_QUIC)
|
||||
if(USE_NGTCP2 OR USE_QUICHE OR USE_MSH3)
|
||||
message(FATAL_ERROR "Only one HTTP/3 backend can be selected!")
|
||||
@@ -788,12 +918,6 @@ if(USE_OPENSSL_QUIC)
|
||||
list(APPEND LIBCURL_PC_REQUIRES_PRIVATE "libnghttp3")
|
||||
endif()
|
||||
|
||||
if(USE_MBEDTLS OR
|
||||
USE_BEARSSL OR
|
||||
USE_SECTRANSP)
|
||||
message(WARNING "A selected TLS library does not support TLS 1.3.")
|
||||
endif()
|
||||
|
||||
if(CURL_WITH_MULTI_SSL AND (USE_NGTCP2 OR USE_QUICHE OR USE_MSH3 OR USE_OPENSSL_QUIC))
|
||||
message(FATAL_ERROR "MultiSSL cannot be enabled with HTTP/3 and vice versa.")
|
||||
endif()
|
||||
@@ -816,7 +940,7 @@ if(NOT CURL_DISABLE_LDAP)
|
||||
set(CMAKE_LDAP_LIB "ldap" CACHE STRING "Name or full path to ldap library")
|
||||
set(CMAKE_LBER_LIB "lber" CACHE STRING "Name or full path to lber library")
|
||||
|
||||
# Now that we know, we're not using windows LDAP...
|
||||
# Now that we know, we are not using Windows LDAP...
|
||||
if(NOT USE_WIN32_LDAP)
|
||||
# Check for LDAP
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_LIBRARIES})
|
||||
@@ -832,37 +956,37 @@ if(NOT CURL_DISABLE_LDAP)
|
||||
if(CMAKE_LDAP_INCLUDE_DIR)
|
||||
list(APPEND CMAKE_REQUIRED_INCLUDES ${CMAKE_LDAP_INCLUDE_DIR})
|
||||
endif()
|
||||
check_include_file_concat("ldap.h" HAVE_LDAP_H)
|
||||
check_include_file_concat("lber.h" HAVE_LBER_H)
|
||||
check_include_file_concat("ldap.h" HAVE_LDAP_H)
|
||||
check_include_file_concat("lber.h" HAVE_LBER_H)
|
||||
|
||||
if(NOT HAVE_LDAP_H)
|
||||
message(STATUS "LDAP_H not found CURL_DISABLE_LDAP set ON")
|
||||
set(CURL_DISABLE_LDAP ON CACHE BOOL "" FORCE)
|
||||
set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES_BAK}) #LDAP includes won't be used
|
||||
set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES_BAK}) # LDAP includes will not be used
|
||||
elseif(NOT HAVE_LIBLDAP)
|
||||
message(STATUS "LDAP library '${CMAKE_LDAP_LIB}' not found CURL_DISABLE_LDAP set ON")
|
||||
set(CURL_DISABLE_LDAP ON CACHE BOOL "" FORCE)
|
||||
set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES_BAK}) #LDAP includes won't be used
|
||||
set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES_BAK}) # LDAP includes will not be used
|
||||
else()
|
||||
if(CMAKE_LDAP_INCLUDE_DIR)
|
||||
include_directories(${CMAKE_LDAP_INCLUDE_DIR})
|
||||
endif()
|
||||
set(NEED_LBER_H ON)
|
||||
set(_HEADER_LIST)
|
||||
unset(_header_list)
|
||||
if(WIN32)
|
||||
list(APPEND _HEADER_LIST "windows.h")
|
||||
list(APPEND _header_list "windows.h")
|
||||
endif()
|
||||
if(HAVE_SYS_TYPES_H)
|
||||
list(APPEND _HEADER_LIST "sys/types.h")
|
||||
list(APPEND _header_list "sys/types.h")
|
||||
endif()
|
||||
list(APPEND _HEADER_LIST "ldap.h")
|
||||
list(APPEND _header_list "ldap.h")
|
||||
|
||||
set(_INCLUDE_STRING "")
|
||||
foreach(_HEADER ${_HEADER_LIST})
|
||||
set(_INCLUDE_STRING "${_INCLUDE_STRING}#include <${_HEADER}>\n")
|
||||
set(_include_string "")
|
||||
foreach(_header IN LISTS _header_list)
|
||||
set(_include_string "${_include_string}#include <${_header}>\n")
|
||||
endforeach()
|
||||
|
||||
list(APPEND CMAKE_REQUIRED_DEFINITIONS -DLDAP_DEPRECATED=1)
|
||||
list(APPEND CMAKE_REQUIRED_DEFINITIONS "-DLDAP_DEPRECATED=1")
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES ${CMAKE_LDAP_LIB})
|
||||
set(CURL_LIBS "${CMAKE_LDAP_LIB};${CURL_LIBS}")
|
||||
if(HAVE_LIBLBER)
|
||||
@@ -871,7 +995,7 @@ if(NOT CURL_DISABLE_LDAP)
|
||||
endif()
|
||||
|
||||
check_c_source_compiles("
|
||||
${_INCLUDE_STRING}
|
||||
${_include_string}
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
BerValue *bvp = NULL;
|
||||
@@ -885,8 +1009,8 @@ if(NOT CURL_DISABLE_LDAP)
|
||||
set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -DNEED_LBER_H")
|
||||
endif()
|
||||
|
||||
check_function_exists(ldap_url_parse HAVE_LDAP_URL_PARSE)
|
||||
check_function_exists(ldap_init_fd HAVE_LDAP_INIT_FD)
|
||||
check_function_exists("ldap_url_parse" HAVE_LDAP_URL_PARSE)
|
||||
check_function_exists("ldap_init_fd" HAVE_LDAP_INIT_FD)
|
||||
|
||||
unset(CMAKE_REQUIRED_LIBRARIES)
|
||||
|
||||
@@ -911,36 +1035,13 @@ if(CURL_DISABLE_LDAP)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Check for idn2
|
||||
option(USE_LIBIDN2 "Use libidn2 for IDN support" ON)
|
||||
if(USE_LIBIDN2)
|
||||
check_library_exists("idn2" "idn2_lookup_ul" "" HAVE_LIBIDN2)
|
||||
if(HAVE_LIBIDN2)
|
||||
set(LIBIDN2_LINK_LIBRARIES "idn2")
|
||||
check_include_file_concat("idn2.h" HAVE_IDN2_H)
|
||||
endif()
|
||||
if(NOT HAVE_LIBIDN2 OR NOT HAVE_IDN2_H)
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(LIBIDN2 "libidn2")
|
||||
if(LIBIDN2_FOUND)
|
||||
include_directories(${LIBIDN2_INCLUDE_DIRS})
|
||||
set(HAVE_LIBIDN2 ON)
|
||||
set(HAVE_IDN2_H ON)
|
||||
endif()
|
||||
endif()
|
||||
if(HAVE_LIBIDN2 AND HAVE_IDN2_H)
|
||||
set(CURL_LIBS "${LIBIDN2_LINK_LIBRARIES};${CURL_LIBS}")
|
||||
set(LIBCURL_PC_REQUIRES_PRIVATE "libidn2;${LIBCURL_PC_REQUIRES_PRIVATE}")
|
||||
endif()
|
||||
else()
|
||||
set(HAVE_LIBIDN2 OFF)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
option(USE_WIN32_IDN "Use WinIDN for IDN support" OFF)
|
||||
if(USE_WIN32_IDN)
|
||||
list(APPEND CURL_LIBS "normaliz")
|
||||
endif()
|
||||
else()
|
||||
set(USE_WIN32_IDN OFF)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
@@ -951,11 +1052,33 @@ if(APPLE)
|
||||
check_symbol_exists("uidna_openUTS46" "unicode/uidna.h" HAVE_APPLE_IDN)
|
||||
cmake_pop_check_state()
|
||||
if(HAVE_APPLE_IDN)
|
||||
list(APPEND CURL_LIBS "icucore")
|
||||
list(APPEND CURL_LIBS "icucore" "iconv")
|
||||
else()
|
||||
set(USE_APPLE_IDN OFF)
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
set(USE_APPLE_IDN OFF)
|
||||
endif()
|
||||
|
||||
# Check for libidn2
|
||||
option(USE_LIBIDN2 "Use libidn2 for IDN support" ON)
|
||||
set(HAVE_IDN2_H OFF)
|
||||
set(HAVE_LIBIDN2 OFF)
|
||||
if(USE_LIBIDN2 AND NOT USE_APPLE_IDN AND NOT USE_WIN32_IDN)
|
||||
find_package(Libidn2)
|
||||
if(LIBIDN2_FOUND)
|
||||
set(CURL_LIBS "${LIBIDN2_LIBRARIES};${CURL_LIBS}")
|
||||
list(APPEND CURL_LIBDIRS ${LIBIDN2_LIBRARY_DIRS})
|
||||
set(LIBCURL_PC_REQUIRES_PRIVATE "libidn2;${LIBCURL_PC_REQUIRES_PRIVATE}")
|
||||
include_directories(${LIBIDN2_INCLUDE_DIRS})
|
||||
link_directories(${LIBIDN2_LIBRARY_DIRS})
|
||||
if(LIBIDN2_CFLAGS)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LIBIDN2_CFLAGS}")
|
||||
endif()
|
||||
set(HAVE_IDN2_H 1)
|
||||
set(HAVE_LIBIDN2 1)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# libpsl
|
||||
@@ -964,28 +1087,30 @@ mark_as_advanced(CURL_USE_LIBPSL)
|
||||
set(USE_LIBPSL OFF)
|
||||
|
||||
if(CURL_USE_LIBPSL)
|
||||
find_package(LibPSL)
|
||||
find_package(Libpsl) # TODO: add REQUIRED to match autotools
|
||||
if(LIBPSL_FOUND)
|
||||
list(APPEND CURL_LIBS ${LIBPSL_LIBRARY})
|
||||
list(APPEND CURL_LIBS ${LIBPSL_LIBRARIES})
|
||||
list(APPEND LIBCURL_PC_REQUIRES_PRIVATE "libpsl")
|
||||
list(APPEND CMAKE_REQUIRED_INCLUDES "${LIBPSL_INCLUDE_DIR}")
|
||||
include_directories("${LIBPSL_INCLUDE_DIR}")
|
||||
list(APPEND CMAKE_REQUIRED_INCLUDES "${LIBPSL_INCLUDE_DIRS}")
|
||||
include_directories(${LIBPSL_INCLUDE_DIRS})
|
||||
set(USE_LIBPSL ON)
|
||||
else()
|
||||
message(WARNING "libpsl is enabled, but not found.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# libssh2
|
||||
option(CURL_USE_LIBSSH2 "Use libssh2" ON)
|
||||
option(CURL_USE_LIBSSH2 "Use libssh2" ON) # FIXME: default is OFF in autotools
|
||||
mark_as_advanced(CURL_USE_LIBSSH2)
|
||||
set(USE_LIBSSH2 OFF)
|
||||
|
||||
if(CURL_USE_LIBSSH2)
|
||||
find_package(LibSSH2)
|
||||
find_package(Libssh2)
|
||||
if(LIBSSH2_FOUND)
|
||||
list(APPEND CURL_LIBS ${LIBSSH2_LIBRARY})
|
||||
list(APPEND CURL_LIBS ${LIBSSH2_LIBRARIES})
|
||||
list(APPEND LIBCURL_PC_REQUIRES_PRIVATE "libssh2")
|
||||
list(APPEND CMAKE_REQUIRED_INCLUDES "${LIBSSH2_INCLUDE_DIR}")
|
||||
include_directories("${LIBSSH2_INCLUDE_DIR}")
|
||||
list(APPEND CMAKE_REQUIRED_INCLUDES "${LIBSSH2_INCLUDE_DIRS}")
|
||||
include_directories(${LIBSSH2_INCLUDE_DIRS})
|
||||
set(USE_LIBSSH2 ON)
|
||||
endif()
|
||||
endif()
|
||||
@@ -994,36 +1119,56 @@ endif()
|
||||
option(CURL_USE_LIBSSH "Use libssh" OFF)
|
||||
mark_as_advanced(CURL_USE_LIBSSH)
|
||||
if(NOT USE_LIBSSH2 AND CURL_USE_LIBSSH)
|
||||
find_package(libssh CONFIG QUIET)
|
||||
if(libssh_FOUND)
|
||||
message(STATUS "Found libssh ${libssh_VERSION}")
|
||||
else()
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(LIBSSH "libssh")
|
||||
if(LIBSSH_FOUND)
|
||||
include_directories(${LIBSSH_INCLUDE_DIRS})
|
||||
endif()
|
||||
endif()
|
||||
if(libssh_FOUND OR LIBSSH_FOUND)
|
||||
if(NOT DEFINED LIBSSH_LINK_LIBRARIES)
|
||||
set(LIBSSH_LINK_LIBRARIES "ssh") # for find_package() with broken pkg-config (e.g. linux-old CI workflow)
|
||||
endif()
|
||||
list(APPEND CURL_LIBS ${LIBSSH_LINK_LIBRARIES})
|
||||
find_package(Libssh REQUIRED)
|
||||
if(LIBSSH_FOUND)
|
||||
list(APPEND CURL_LIBS ${LIBSSH_LIBRARIES})
|
||||
list(APPEND CURL_LIBDIRS ${LIBSSH_LIBRARY_DIRS})
|
||||
list(APPEND LIBCURL_PC_REQUIRES_PRIVATE "libssh")
|
||||
include_directories(${LIBSSH_INCLUDE_DIRS})
|
||||
link_directories(${LIBSSH_LIBRARY_DIRS})
|
||||
if(LIBSSH_CFLAGS)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LIBSSH_CFLAGS}")
|
||||
endif()
|
||||
set(USE_LIBSSH ON)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(CURL_USE_GSASL "Use GSASL implementation" OFF)
|
||||
mark_as_advanced(CURL_USE_GSASL)
|
||||
if(CURL_USE_GSASL)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(GSASL REQUIRED libgsasl)
|
||||
list(APPEND CURL_LIBS ${GSASL_LINK_LIBRARIES})
|
||||
set(USE_GSASL ON)
|
||||
# wolfSSH
|
||||
option(CURL_USE_WOLFSSH "Use wolfSSH" OFF)
|
||||
mark_as_advanced(CURL_USE_WOLFSSH)
|
||||
set(USE_WOLFSSH OFF)
|
||||
if(NOT USE_LIBSSH2 AND NOT USE_LIBSSH AND CURL_USE_WOLFSSH)
|
||||
if(USE_WOLFSSL)
|
||||
find_package(WolfSSH)
|
||||
if(WOLFSSH_FOUND)
|
||||
list(APPEND CURL_LIBS ${WOLFSSH_LIBRARIES})
|
||||
list(APPEND CMAKE_REQUIRED_INCLUDES "${WOLFSSH_INCLUDE_DIRS}")
|
||||
include_directories(${WOLFSSH_INCLUDE_DIRS})
|
||||
set(USE_WOLFSSH ON)
|
||||
endif()
|
||||
else()
|
||||
message(WARNING "wolfSSH requires wolfSSL. Skipping.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(CURL_USE_GSSAPI "Use GSSAPI implementation (right now only Heimdal is supported with CMake build)" OFF)
|
||||
option(CURL_USE_GSASL "Use libgsasl" OFF)
|
||||
mark_as_advanced(CURL_USE_GSASL)
|
||||
if(CURL_USE_GSASL)
|
||||
find_package(Libgsasl REQUIRED)
|
||||
if(LIBGSASL_FOUND)
|
||||
list(APPEND CURL_LIBS ${LIBGSASL_LIBRARIES})
|
||||
list(APPEND CURL_LIBDIRS ${LIBGSASL_LIBRARY_DIRS})
|
||||
list(APPEND LIBCURL_PC_REQUIRES_PRIVATE "libgsasl")
|
||||
include_directories(${LIBGSASL_INCLUDE_DIRS})
|
||||
link_directories(${LIBGSASL_LIBRARY_DIRS})
|
||||
if(LIBGSASL_CFLAGS)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LIBGSASL_CFLAGS}")
|
||||
endif()
|
||||
set(USE_GSASL ON)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(CURL_USE_GSSAPI "Use GSSAPI implementation" OFF)
|
||||
mark_as_advanced(CURL_USE_GSSAPI)
|
||||
|
||||
if(CURL_USE_GSSAPI)
|
||||
@@ -1031,38 +1176,35 @@ if(CURL_USE_GSSAPI)
|
||||
|
||||
set(HAVE_GSSAPI ${GSS_FOUND})
|
||||
if(GSS_FOUND)
|
||||
list(APPEND CMAKE_REQUIRED_INCLUDES ${GSS_INCLUDE_DIRS})
|
||||
|
||||
message(STATUS "Found ${GSS_FLAVOUR} GSSAPI version: \"${GSS_VERSION}\"")
|
||||
string(REPLACE ";" " " GSS_CFLAGS "${GSS_CFLAGS}")
|
||||
string(REPLACE ";" " " GSS_LDFLAGS "${GSS_LDFLAGS}")
|
||||
|
||||
list(APPEND CMAKE_REQUIRED_INCLUDES ${GSS_INCLUDE_DIR})
|
||||
check_include_file_concat("gssapi/gssapi.h" HAVE_GSSAPI_GSSAPI_H)
|
||||
foreach(_dir IN LISTS GSS_LIBRARY_DIRS)
|
||||
set(GSS_LDFLAGS "${GSS_LDFLAGS} -L\"${_dir}\"")
|
||||
endforeach()
|
||||
|
||||
check_include_file_concat("gssapi/gssapi.h" HAVE_GSSAPI_GSSAPI_H)
|
||||
check_include_file_concat("gssapi/gssapi_generic.h" HAVE_GSSAPI_GSSAPI_GENERIC_H)
|
||||
check_include_file_concat("gssapi/gssapi_krb5.h" HAVE_GSSAPI_GSSAPI_KRB5_H)
|
||||
|
||||
if(NOT GSS_FLAVOUR STREQUAL "Heimdal")
|
||||
# MIT
|
||||
set(_INCLUDE_LIST "")
|
||||
if(GSS_FLAVOUR STREQUAL "MIT")
|
||||
set(_include_list "")
|
||||
if(HAVE_GSSAPI_GSSAPI_H)
|
||||
list(APPEND _INCLUDE_LIST "gssapi/gssapi.h")
|
||||
list(APPEND _include_list "gssapi/gssapi.h")
|
||||
endif()
|
||||
if(HAVE_GSSAPI_GSSAPI_GENERIC_H)
|
||||
list(APPEND _INCLUDE_LIST "gssapi/gssapi_generic.h")
|
||||
list(APPEND _include_list "gssapi/gssapi_generic.h")
|
||||
endif()
|
||||
if(HAVE_GSSAPI_GSSAPI_KRB5_H)
|
||||
list(APPEND _INCLUDE_LIST "gssapi/gssapi_krb5.h")
|
||||
list(APPEND _include_list "gssapi/gssapi_krb5.h")
|
||||
endif()
|
||||
|
||||
string(REPLACE ";" " " _COMPILER_FLAGS_STR "${GSS_COMPILER_FLAGS}")
|
||||
string(REPLACE ";" " " _LINKER_FLAGS_STR "${GSS_LINKER_FLAGS}")
|
||||
|
||||
foreach(_dir ${GSS_LINK_DIRECTORIES})
|
||||
set(_LINKER_FLAGS_STR "${_LINKER_FLAGS_STR} -L\"${_dir}\"")
|
||||
endforeach()
|
||||
|
||||
if(NOT DEFINED HAVE_GSS_C_NT_HOSTBASED_SERVICE)
|
||||
set(CMAKE_REQUIRED_FLAGS "${_COMPILER_FLAGS_STR} ${_LINKER_FLAGS_STR}")
|
||||
set(CMAKE_REQUIRED_FLAGS "${GSS_CFLAGS} ${GSS_LDFLAGS}")
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${GSS_LIBRARIES})
|
||||
check_symbol_exists("GSS_C_NT_HOSTBASED_SERVICE" ${_INCLUDE_LIST} HAVE_GSS_C_NT_HOSTBASED_SERVICE)
|
||||
check_symbol_exists("GSS_C_NT_HOSTBASED_SERVICE" ${_include_list} HAVE_GSS_C_NT_HOSTBASED_SERVICE)
|
||||
unset(CMAKE_REQUIRED_LIBRARIES)
|
||||
endif()
|
||||
if(NOT HAVE_GSS_C_NT_HOSTBASED_SERVICE)
|
||||
@@ -1070,21 +1212,43 @@ if(CURL_USE_GSSAPI)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include_directories(${GSS_INCLUDE_DIR})
|
||||
link_directories(${GSS_LINK_DIRECTORIES})
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GSS_COMPILER_FLAGS}")
|
||||
string(REPLACE ";" " " GSS_LINKER_FLAGS "${GSS_LINKER_FLAGS}")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${GSS_LINKER_FLAGS}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GSS_LINKER_FLAGS}")
|
||||
include_directories(${GSS_INCLUDE_DIRS})
|
||||
link_directories(${GSS_LIBRARY_DIRS})
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GSS_CFLAGS}")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${GSS_LDFLAGS}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GSS_LDFLAGS}")
|
||||
list(APPEND CURL_LIBS ${GSS_LIBRARIES})
|
||||
if(GSS_FLAVOUR STREQUAL "MIT")
|
||||
list(APPEND LIBCURL_PC_REQUIRES_PRIVATE "mit-krb5-gssapi")
|
||||
else() # Heimdal
|
||||
list(APPEND LIBCURL_PC_REQUIRES_PRIVATE "heimdal-gssapi")
|
||||
endif()
|
||||
else()
|
||||
message(WARNING "GSSAPI support has been requested but no supporting libraries found. Skipping.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# libuv
|
||||
option(CURL_USE_LIBUV "Use libuv for event-based tests" OFF)
|
||||
if(CURL_USE_LIBUV)
|
||||
if(NOT ENABLE_DEBUG)
|
||||
message(FATAL_ERROR "Using libuv without debug support enabled is useless")
|
||||
endif()
|
||||
find_package(Libuv REQUIRED)
|
||||
if(LIBUV_FOUND)
|
||||
list(APPEND CURL_LIBS ${LIBUV_LIBRARIES})
|
||||
list(APPEND CURL_LIBDIRS ${LIBUV_LIBRARY_DIRS})
|
||||
list(APPEND LIBCURL_PC_REQUIRES_PRIVATE "libuv")
|
||||
include_directories(${LIBUV_INCLUDE_DIRS})
|
||||
link_directories(${LIBUV_LIBRARY_DIRS})
|
||||
if(LIBUV_CFLAGS)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LIBUV_CFLAGS}")
|
||||
endif()
|
||||
set(USE_LIBUV ON)
|
||||
set(HAVE_UV_H ON)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(USE_LIBRTMP "Enable librtmp from rtmpdump" OFF)
|
||||
if(USE_LIBRTMP)
|
||||
cmake_push_check_state()
|
||||
@@ -1106,13 +1270,13 @@ if(USE_LIBRTMP)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(ENABLE_UNIX_SOCKETS "Define if you want Unix domain sockets support" ON)
|
||||
option(ENABLE_UNIX_SOCKETS "Enable Unix domain sockets support" ON)
|
||||
if(ENABLE_UNIX_SOCKETS)
|
||||
include(CheckStructHasMember)
|
||||
if(WIN32)
|
||||
set(USE_UNIX_SOCKETS ON)
|
||||
else()
|
||||
check_struct_has_member("struct sockaddr_un" sun_path "sys/un.h" USE_UNIX_SOCKETS)
|
||||
include(CheckStructHasMember)
|
||||
check_struct_has_member("struct sockaddr_un" "sun_path" "sys/un.h" USE_UNIX_SOCKETS)
|
||||
endif()
|
||||
else()
|
||||
unset(USE_UNIX_SOCKETS CACHE)
|
||||
@@ -1121,13 +1285,15 @@ endif()
|
||||
#
|
||||
# CA handling
|
||||
#
|
||||
if(curl_ca_bundle_supported)
|
||||
set(CURL_CA_BUNDLE "auto" CACHE STRING
|
||||
"Path to the CA bundle. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.")
|
||||
if(_curl_ca_bundle_supported)
|
||||
set(CURL_CA_BUNDLE "auto" CACHE
|
||||
STRING "Path to the CA bundle. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.")
|
||||
set(CURL_CA_FALLBACK OFF CACHE BOOL
|
||||
"Set ON to use built-in CA store of TLS backend. Defaults to OFF")
|
||||
set(CURL_CA_PATH "auto" CACHE STRING
|
||||
"Location of default CA path. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.")
|
||||
"Set ON to use built-in CA store of TLS backend. Defaults to OFF")
|
||||
set(CURL_CA_PATH "auto" CACHE
|
||||
STRING "Location of default CA path. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.")
|
||||
set(CURL_CA_EMBED "" CACHE
|
||||
STRING "Path to the CA bundle to embed into the curl tool.")
|
||||
|
||||
if(CURL_CA_BUNDLE STREQUAL "")
|
||||
message(FATAL_ERROR "Invalid value of CURL_CA_BUNDLE. Use 'none', 'auto' or file path.")
|
||||
@@ -1136,11 +1302,12 @@ if(curl_ca_bundle_supported)
|
||||
elseif(CURL_CA_BUNDLE STREQUAL "auto")
|
||||
unset(CURL_CA_BUNDLE CACHE)
|
||||
if(NOT CMAKE_CROSSCOMPILING AND NOT WIN32)
|
||||
set(CURL_CA_BUNDLE_AUTODETECT TRUE)
|
||||
set(_curl_ca_bundle_autodetect TRUE)
|
||||
endif()
|
||||
else()
|
||||
set(CURL_CA_BUNDLE_SET TRUE)
|
||||
endif()
|
||||
mark_as_advanced(CURL_CA_BUNDLE_SET)
|
||||
|
||||
if(CURL_CA_PATH STREQUAL "")
|
||||
message(FATAL_ERROR "Invalid value of CURL_CA_PATH. Use 'none', 'auto' or directory path.")
|
||||
@@ -1149,48 +1316,58 @@ if(curl_ca_bundle_supported)
|
||||
elseif(CURL_CA_PATH STREQUAL "auto")
|
||||
unset(CURL_CA_PATH CACHE)
|
||||
if(NOT CMAKE_CROSSCOMPILING AND NOT WIN32)
|
||||
set(CURL_CA_PATH_AUTODETECT TRUE)
|
||||
set(_curl_ca_path_autodetect TRUE)
|
||||
endif()
|
||||
else()
|
||||
set(CURL_CA_PATH_SET TRUE)
|
||||
endif()
|
||||
mark_as_advanced(CURL_CA_PATH_SET)
|
||||
|
||||
if(CURL_CA_BUNDLE_SET AND CURL_CA_PATH_AUTODETECT)
|
||||
if(CURL_CA_BUNDLE_SET AND _curl_ca_path_autodetect)
|
||||
# Skip auto-detection of unset CA path because CA bundle is set explicitly
|
||||
elseif(CURL_CA_PATH_SET AND CURL_CA_BUNDLE_AUTODETECT)
|
||||
elseif(CURL_CA_PATH_SET AND _curl_ca_bundle_autodetect)
|
||||
# Skip auto-detection of unset CA bundle because CA path is set explicitly
|
||||
elseif(CURL_CA_BUNDLE_AUTODETECT OR CURL_CA_PATH_AUTODETECT)
|
||||
elseif(_curl_ca_bundle_autodetect OR _curl_ca_path_autodetect)
|
||||
# First try auto-detecting a CA bundle, then a CA path
|
||||
|
||||
if(CURL_CA_BUNDLE_AUTODETECT)
|
||||
foreach(SEARCH_CA_BUNDLE_PATH IN ITEMS
|
||||
if(_curl_ca_bundle_autodetect)
|
||||
foreach(_search_ca_bundle_path IN ITEMS
|
||||
"/etc/ssl/certs/ca-certificates.crt"
|
||||
"/etc/pki/tls/certs/ca-bundle.crt"
|
||||
"/usr/share/ssl/certs/ca-bundle.crt"
|
||||
"/usr/local/share/certs/ca-root-nss.crt"
|
||||
"/etc/ssl/cert.pem")
|
||||
if(EXISTS "${SEARCH_CA_BUNDLE_PATH}")
|
||||
message(STATUS "Found CA bundle: ${SEARCH_CA_BUNDLE_PATH}")
|
||||
set(CURL_CA_BUNDLE "${SEARCH_CA_BUNDLE_PATH}" CACHE STRING
|
||||
"Path to the CA bundle. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.")
|
||||
if(EXISTS "${_search_ca_bundle_path}")
|
||||
message(STATUS "Found CA bundle: ${_search_ca_bundle_path}")
|
||||
set(CURL_CA_BUNDLE "${_search_ca_bundle_path}" CACHE
|
||||
STRING "Path to the CA bundle. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.")
|
||||
set(CURL_CA_BUNDLE_SET TRUE CACHE BOOL "Path to the CA bundle has been set")
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if(CURL_CA_PATH_AUTODETECT AND NOT CURL_CA_PATH_SET)
|
||||
set(SEARCH_CA_PATH "/etc/ssl/certs")
|
||||
file(GLOB curl_ca_files_found "${SEARCH_CA_PATH}/[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f].0")
|
||||
if(curl_ca_files_found)
|
||||
unset(curl_ca_files_found)
|
||||
message(STATUS "Found CA path: ${SEARCH_CA_PATH}")
|
||||
set(CURL_CA_PATH "${SEARCH_CA_PATH}" CACHE STRING
|
||||
"Location of default CA path. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.")
|
||||
if(_curl_ca_path_autodetect AND NOT CURL_CA_PATH_SET)
|
||||
set(_search_ca_path "/etc/ssl/certs")
|
||||
file(GLOB _curl_ca_files_found "${_search_ca_path}/[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f].0")
|
||||
if(_curl_ca_files_found)
|
||||
unset(_curl_ca_files_found)
|
||||
message(STATUS "Found CA path: ${_search_ca_path}")
|
||||
set(CURL_CA_PATH "${_search_ca_path}" CACHE
|
||||
STRING "Location of default CA path. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.")
|
||||
set(CURL_CA_PATH_SET TRUE CACHE BOOL "Path to the CA bundle has been set")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CURL_CA_EMBED_SET FALSE)
|
||||
if(BUILD_CURL_EXE AND NOT CURL_CA_EMBED STREQUAL "")
|
||||
if(EXISTS "${CURL_CA_EMBED}")
|
||||
set(CURL_CA_EMBED_SET TRUE)
|
||||
else()
|
||||
message(FATAL_ERROR "CA bundle to embed is missing: '${CURL_CA_EMBED}'")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Check for header files
|
||||
@@ -1198,30 +1375,16 @@ if(WIN32)
|
||||
set(CURL_INCLUDES ${CURL_INCLUDES} "winsock2.h")
|
||||
set(CURL_INCLUDES ${CURL_INCLUDES} "ws2tcpip.h")
|
||||
set(CURL_INCLUDES ${CURL_INCLUDES} "windows.h")
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
# detect actual value of _WIN32_WINNT and store as HAVE_WIN32_WINNT
|
||||
curl_internal_test(HAVE_WIN32_WINNT)
|
||||
if(HAVE_WIN32_WINNT)
|
||||
string(REGEX MATCH ".*_WIN32_WINNT=0x[0-9a-fA-F]+" OUTPUT "${OUTPUT}")
|
||||
string(REGEX REPLACE ".*_WIN32_WINNT=" "" OUTPUT "${OUTPUT}")
|
||||
string(REGEX REPLACE "0x([0-9a-f][0-9a-f][0-9a-f])$" "0x0\\1" OUTPUT "${OUTPUT}") # pad to 4 digits
|
||||
string(TOLOWER "${OUTPUT}" HAVE_WIN32_WINNT)
|
||||
message(STATUS "Found _WIN32_WINNT=${HAVE_WIN32_WINNT}")
|
||||
endif()
|
||||
# avoid storing HAVE_WIN32_WINNT in CMake cache
|
||||
unset(HAVE_WIN32_WINNT CACHE)
|
||||
|
||||
if(HAVE_WIN32_WINNT)
|
||||
if(HAVE_WIN32_WINNT STRLESS "0x0501")
|
||||
if(HAVE_WIN32_WINNT LESS 0x0501)
|
||||
# Windows XP is required for freeaddrinfo, getaddrinfo
|
||||
message(FATAL_ERROR "Building for Windows XP or newer is required.")
|
||||
endif()
|
||||
|
||||
# pre-fill detection results based on target OS version
|
||||
# Pre-fill detection results based on target OS version
|
||||
if(MINGW OR MSVC)
|
||||
if(HAVE_WIN32_WINNT STRLESS "0x0600")
|
||||
if(HAVE_WIN32_WINNT LESS 0x0600)
|
||||
set(HAVE_INET_NTOP 0)
|
||||
set(HAVE_INET_PTON 0)
|
||||
else() # Windows Vista or newer
|
||||
@@ -1275,20 +1438,20 @@ check_include_file_concat("termios.h" HAVE_TERMIOS_H)
|
||||
check_include_file_concat("unistd.h" HAVE_UNISTD_H)
|
||||
check_include_file_concat("utime.h" HAVE_UTIME_H)
|
||||
|
||||
check_type_size(size_t SIZEOF_SIZE_T)
|
||||
check_type_size(ssize_t SIZEOF_SSIZE_T)
|
||||
check_type_size("long long" SIZEOF_LONG_LONG)
|
||||
check_type_size("long" SIZEOF_LONG)
|
||||
check_type_size("int" SIZEOF_INT)
|
||||
check_type_size("__int64" SIZEOF___INT64)
|
||||
check_type_size("time_t" SIZEOF_TIME_T)
|
||||
check_type_size("suseconds_t" SIZEOF_SUSECONDS_T)
|
||||
check_type_size("size_t" SIZEOF_SIZE_T)
|
||||
check_type_size("ssize_t" SIZEOF_SSIZE_T)
|
||||
check_type_size("long long" SIZEOF_LONG_LONG)
|
||||
check_type_size("long" SIZEOF_LONG)
|
||||
check_type_size("int" SIZEOF_INT)
|
||||
check_type_size("__int64" SIZEOF___INT64)
|
||||
check_type_size("time_t" SIZEOF_TIME_T)
|
||||
check_type_size("suseconds_t" SIZEOF_SUSECONDS_T)
|
||||
if(NOT HAVE_SIZEOF_SSIZE_T)
|
||||
if(SIZEOF_LONG EQUAL SIZEOF_SIZE_T)
|
||||
set(ssize_t long)
|
||||
set(ssize_t "long")
|
||||
endif()
|
||||
if(NOT ssize_t AND SIZEOF___INT64 EQUAL SIZEOF_SIZE_T)
|
||||
set(ssize_t __int64)
|
||||
set(ssize_t "__int64")
|
||||
endif()
|
||||
endif()
|
||||
# off_t is sized later, after the HAVE_FILE_OFFSET_BITS test
|
||||
@@ -1300,104 +1463,99 @@ if(SIZEOF_SUSECONDS_T)
|
||||
set(HAVE_SUSECONDS_T 1)
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_CROSSCOMPILING)
|
||||
find_file(RANDOM_FILE urandom /dev)
|
||||
mark_as_advanced(RANDOM_FILE)
|
||||
endif()
|
||||
|
||||
# Check for some functions that are used
|
||||
if(WIN32)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ws2_32)
|
||||
set(CMAKE_REQUIRED_LIBRARIES "ws2_32")
|
||||
elseif(HAVE_LIBSOCKET)
|
||||
set(CMAKE_REQUIRED_LIBRARIES socket)
|
||||
set(CMAKE_REQUIRED_LIBRARIES "socket")
|
||||
endif()
|
||||
|
||||
check_symbol_exists(fnmatch "${CURL_INCLUDES};fnmatch.h" HAVE_FNMATCH)
|
||||
check_symbol_exists(basename "${CURL_INCLUDES};string.h" HAVE_BASENAME)
|
||||
check_symbol_exists(opendir "${CURL_INCLUDES};dirent.h" HAVE_OPENDIR)
|
||||
check_symbol_exists(socket "${CURL_INCLUDES}" HAVE_SOCKET)
|
||||
check_symbol_exists(sched_yield "${CURL_INCLUDES};sched.h" HAVE_SCHED_YIELD)
|
||||
check_symbol_exists(socketpair "${CURL_INCLUDES}" HAVE_SOCKETPAIR)
|
||||
check_symbol_exists(recv "${CURL_INCLUDES}" HAVE_RECV)
|
||||
check_symbol_exists(send "${CURL_INCLUDES}" HAVE_SEND)
|
||||
check_symbol_exists(sendmsg "${CURL_INCLUDES}" HAVE_SENDMSG)
|
||||
check_symbol_exists(select "${CURL_INCLUDES}" HAVE_SELECT)
|
||||
check_symbol_exists(strdup "${CURL_INCLUDES};string.h" HAVE_STRDUP)
|
||||
check_symbol_exists(strtok_r "${CURL_INCLUDES};string.h" HAVE_STRTOK_R)
|
||||
check_symbol_exists(strcasecmp "${CURL_INCLUDES};string.h" HAVE_STRCASECMP)
|
||||
check_symbol_exists(stricmp "${CURL_INCLUDES};string.h" HAVE_STRICMP)
|
||||
check_symbol_exists(strcmpi "${CURL_INCLUDES};string.h" HAVE_STRCMPI)
|
||||
check_symbol_exists(memrchr "${CURL_INCLUDES};string.h" HAVE_MEMRCHR)
|
||||
check_symbol_exists(alarm "${CURL_INCLUDES}" HAVE_ALARM)
|
||||
check_symbol_exists(arc4random "${CURL_INCLUDES};stdlib.h" HAVE_ARC4RANDOM)
|
||||
check_symbol_exists(fcntl "${CURL_INCLUDES}" HAVE_FCNTL)
|
||||
check_symbol_exists(getppid "${CURL_INCLUDES}" HAVE_GETPPID)
|
||||
check_symbol_exists(utimes "${CURL_INCLUDES}" HAVE_UTIMES)
|
||||
check_symbol_exists("fnmatch" "${CURL_INCLUDES};fnmatch.h" HAVE_FNMATCH)
|
||||
check_symbol_exists("basename" "${CURL_INCLUDES};string.h" HAVE_BASENAME)
|
||||
check_symbol_exists("opendir" "${CURL_INCLUDES};dirent.h" HAVE_OPENDIR)
|
||||
check_symbol_exists("socket" "${CURL_INCLUDES}" HAVE_SOCKET)
|
||||
check_symbol_exists("sched_yield" "${CURL_INCLUDES};sched.h" HAVE_SCHED_YIELD)
|
||||
check_symbol_exists("socketpair" "${CURL_INCLUDES}" HAVE_SOCKETPAIR)
|
||||
check_symbol_exists("recv" "${CURL_INCLUDES}" HAVE_RECV)
|
||||
check_symbol_exists("send" "${CURL_INCLUDES}" HAVE_SEND)
|
||||
check_symbol_exists("sendmsg" "${CURL_INCLUDES}" HAVE_SENDMSG)
|
||||
check_symbol_exists("select" "${CURL_INCLUDES}" HAVE_SELECT)
|
||||
check_symbol_exists("strdup" "${CURL_INCLUDES};string.h" HAVE_STRDUP)
|
||||
check_symbol_exists("strtok_r" "${CURL_INCLUDES};string.h" HAVE_STRTOK_R)
|
||||
check_symbol_exists("strcasecmp" "${CURL_INCLUDES};string.h" HAVE_STRCASECMP)
|
||||
check_symbol_exists("stricmp" "${CURL_INCLUDES};string.h" HAVE_STRICMP)
|
||||
check_symbol_exists("strcmpi" "${CURL_INCLUDES};string.h" HAVE_STRCMPI)
|
||||
check_symbol_exists("memrchr" "${CURL_INCLUDES};string.h" HAVE_MEMRCHR)
|
||||
check_symbol_exists("alarm" "${CURL_INCLUDES}" HAVE_ALARM)
|
||||
check_symbol_exists("arc4random" "${CURL_INCLUDES};stdlib.h" HAVE_ARC4RANDOM)
|
||||
check_symbol_exists("fcntl" "${CURL_INCLUDES}" HAVE_FCNTL)
|
||||
check_symbol_exists("getppid" "${CURL_INCLUDES}" HAVE_GETPPID)
|
||||
check_symbol_exists("utimes" "${CURL_INCLUDES}" HAVE_UTIMES)
|
||||
|
||||
check_symbol_exists(gettimeofday "${CURL_INCLUDES}" HAVE_GETTIMEOFDAY)
|
||||
check_symbol_exists(closesocket "${CURL_INCLUDES}" HAVE_CLOSESOCKET)
|
||||
check_symbol_exists(sigsetjmp "${CURL_INCLUDES};setjmp.h" HAVE_SIGSETJMP)
|
||||
check_symbol_exists(getpass_r "${CURL_INCLUDES}" HAVE_GETPASS_R)
|
||||
check_symbol_exists(getpwuid "${CURL_INCLUDES}" HAVE_GETPWUID)
|
||||
check_symbol_exists(getpwuid_r "${CURL_INCLUDES}" HAVE_GETPWUID_R)
|
||||
check_symbol_exists(geteuid "${CURL_INCLUDES}" HAVE_GETEUID)
|
||||
check_symbol_exists(utime "${CURL_INCLUDES}" HAVE_UTIME)
|
||||
check_symbol_exists(gmtime_r "${CURL_INCLUDES};stdlib.h;time.h" HAVE_GMTIME_R)
|
||||
check_symbol_exists("gettimeofday" "${CURL_INCLUDES}" HAVE_GETTIMEOFDAY)
|
||||
check_symbol_exists("closesocket" "${CURL_INCLUDES}" HAVE_CLOSESOCKET)
|
||||
check_symbol_exists("sigsetjmp" "${CURL_INCLUDES};setjmp.h" HAVE_SIGSETJMP)
|
||||
check_symbol_exists("getpass_r" "${CURL_INCLUDES}" HAVE_GETPASS_R)
|
||||
check_symbol_exists("getpwuid" "${CURL_INCLUDES}" HAVE_GETPWUID)
|
||||
check_symbol_exists("getpwuid_r" "${CURL_INCLUDES}" HAVE_GETPWUID_R)
|
||||
check_symbol_exists("geteuid" "${CURL_INCLUDES}" HAVE_GETEUID)
|
||||
check_symbol_exists("utime" "${CURL_INCLUDES}" HAVE_UTIME)
|
||||
check_symbol_exists("gmtime_r" "${CURL_INCLUDES};stdlib.h;time.h" HAVE_GMTIME_R)
|
||||
|
||||
check_symbol_exists(gethostbyname_r "${CURL_INCLUDES}" HAVE_GETHOSTBYNAME_R)
|
||||
check_symbol_exists("gethostbyname_r" "${CURL_INCLUDES}" HAVE_GETHOSTBYNAME_R)
|
||||
|
||||
check_symbol_exists(signal "${CURL_INCLUDES};signal.h" HAVE_SIGNAL)
|
||||
check_symbol_exists(strtoll "${CURL_INCLUDES};stdlib.h" HAVE_STRTOLL)
|
||||
check_symbol_exists(strerror_r "${CURL_INCLUDES};stdlib.h;string.h" HAVE_STRERROR_R)
|
||||
check_symbol_exists(sigaction "signal.h" HAVE_SIGACTION)
|
||||
check_symbol_exists(siginterrupt "${CURL_INCLUDES};signal.h" HAVE_SIGINTERRUPT)
|
||||
check_symbol_exists(getaddrinfo "${CURL_INCLUDES};stdlib.h;string.h" HAVE_GETADDRINFO)
|
||||
check_symbol_exists(getifaddrs "${CURL_INCLUDES};stdlib.h" HAVE_GETIFADDRS)
|
||||
check_symbol_exists(freeaddrinfo "${CURL_INCLUDES}" HAVE_FREEADDRINFO)
|
||||
check_symbol_exists(pipe "${CURL_INCLUDES}" HAVE_PIPE)
|
||||
check_symbol_exists(eventfd "${CURL_INCLUDES};sys/eventfd.h" HAVE_EVENTFD)
|
||||
check_symbol_exists(ftruncate "${CURL_INCLUDES}" HAVE_FTRUNCATE)
|
||||
check_symbol_exists(_fseeki64 "${CURL_INCLUDES};stdio.h" HAVE__FSEEKI64)
|
||||
check_symbol_exists(getpeername "${CURL_INCLUDES}" HAVE_GETPEERNAME)
|
||||
check_symbol_exists(getsockname "${CURL_INCLUDES}" HAVE_GETSOCKNAME)
|
||||
check_symbol_exists(if_nametoindex "${CURL_INCLUDES}" HAVE_IF_NAMETOINDEX)
|
||||
check_symbol_exists(getrlimit "${CURL_INCLUDES}" HAVE_GETRLIMIT)
|
||||
check_symbol_exists(setlocale "${CURL_INCLUDES}" HAVE_SETLOCALE)
|
||||
check_symbol_exists(setmode "${CURL_INCLUDES}" HAVE_SETMODE)
|
||||
check_symbol_exists(setrlimit "${CURL_INCLUDES}" HAVE_SETRLIMIT)
|
||||
check_symbol_exists("signal" "${CURL_INCLUDES};signal.h" HAVE_SIGNAL)
|
||||
check_symbol_exists("strtoll" "${CURL_INCLUDES};stdlib.h" HAVE_STRTOLL)
|
||||
check_symbol_exists("strerror_r" "${CURL_INCLUDES};stdlib.h;string.h" HAVE_STRERROR_R)
|
||||
check_symbol_exists("sigaction" "signal.h" HAVE_SIGACTION)
|
||||
check_symbol_exists("siginterrupt" "${CURL_INCLUDES};signal.h" HAVE_SIGINTERRUPT)
|
||||
check_symbol_exists("getaddrinfo" "${CURL_INCLUDES};stdlib.h;string.h" HAVE_GETADDRINFO)
|
||||
check_symbol_exists("getifaddrs" "${CURL_INCLUDES};stdlib.h" HAVE_GETIFADDRS)
|
||||
check_symbol_exists("freeaddrinfo" "${CURL_INCLUDES}" HAVE_FREEADDRINFO)
|
||||
check_symbol_exists("pipe" "${CURL_INCLUDES}" HAVE_PIPE)
|
||||
check_symbol_exists("eventfd" "${CURL_INCLUDES};sys/eventfd.h" HAVE_EVENTFD)
|
||||
check_symbol_exists("ftruncate" "${CURL_INCLUDES}" HAVE_FTRUNCATE)
|
||||
check_symbol_exists("_fseeki64" "${CURL_INCLUDES};stdio.h" HAVE__FSEEKI64)
|
||||
check_symbol_exists("getpeername" "${CURL_INCLUDES}" HAVE_GETPEERNAME)
|
||||
check_symbol_exists("getsockname" "${CURL_INCLUDES}" HAVE_GETSOCKNAME)
|
||||
check_symbol_exists("if_nametoindex" "${CURL_INCLUDES}" HAVE_IF_NAMETOINDEX)
|
||||
check_symbol_exists("getrlimit" "${CURL_INCLUDES}" HAVE_GETRLIMIT)
|
||||
check_symbol_exists("setlocale" "${CURL_INCLUDES}" HAVE_SETLOCALE)
|
||||
check_symbol_exists("setmode" "${CURL_INCLUDES}" HAVE_SETMODE)
|
||||
check_symbol_exists("setrlimit" "${CURL_INCLUDES}" HAVE_SETRLIMIT)
|
||||
|
||||
if(NOT MSVC OR (MSVC_VERSION GREATER_EQUAL 1900))
|
||||
# earlier MSVC compilers had faulty snprintf implementations
|
||||
check_symbol_exists(snprintf "stdio.h" HAVE_SNPRINTF)
|
||||
# Earlier MSVC compilers had faulty snprintf implementations
|
||||
check_symbol_exists("snprintf" "stdio.h" HAVE_SNPRINTF)
|
||||
endif()
|
||||
check_function_exists(mach_absolute_time HAVE_MACH_ABSOLUTE_TIME)
|
||||
check_symbol_exists(inet_ntop "${CURL_INCLUDES};stdlib.h;string.h" HAVE_INET_NTOP)
|
||||
check_function_exists("mach_absolute_time" HAVE_MACH_ABSOLUTE_TIME)
|
||||
check_symbol_exists("inet_ntop" "${CURL_INCLUDES};stdlib.h;string.h" HAVE_INET_NTOP)
|
||||
if(MSVC AND (MSVC_VERSION LESS_EQUAL 1600))
|
||||
set(HAVE_INET_NTOP OFF)
|
||||
endif()
|
||||
check_symbol_exists(inet_pton "${CURL_INCLUDES};stdlib.h;string.h" HAVE_INET_PTON)
|
||||
check_symbol_exists("inet_pton" "${CURL_INCLUDES};stdlib.h;string.h" HAVE_INET_PTON)
|
||||
|
||||
check_symbol_exists(fsetxattr "${CURL_INCLUDES}" HAVE_FSETXATTR)
|
||||
check_symbol_exists("fsetxattr" "${CURL_INCLUDES}" HAVE_FSETXATTR)
|
||||
if(HAVE_FSETXATTR)
|
||||
foreach(CURL_TEST HAVE_FSETXATTR_5 HAVE_FSETXATTR_6)
|
||||
curl_internal_test(${CURL_TEST})
|
||||
foreach(_curl_test IN ITEMS HAVE_FSETXATTR_5 HAVE_FSETXATTR_6)
|
||||
curl_internal_test(${_curl_test})
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
set(CMAKE_EXTRA_INCLUDE_FILES "sys/socket.h")
|
||||
check_type_size("sa_family_t" SIZEOF_SA_FAMILY_T)
|
||||
set(HAVE_SA_FAMILY_T ${HAVE_SIZEOF_SA_FAMILY_T})
|
||||
set(CMAKE_EXTRA_INCLUDE_FILES "")
|
||||
set(CMAKE_EXTRA_INCLUDE_FILES "sys/socket.h")
|
||||
check_type_size("sa_family_t" SIZEOF_SA_FAMILY_T)
|
||||
set(HAVE_SA_FAMILY_T ${HAVE_SIZEOF_SA_FAMILY_T})
|
||||
set(CMAKE_EXTRA_INCLUDE_FILES "")
|
||||
|
||||
if(WIN32)
|
||||
set(CMAKE_EXTRA_INCLUDE_FILES "winsock2.h")
|
||||
check_type_size("ADDRESS_FAMILY" SIZEOF_ADDRESS_FAMILY)
|
||||
set(HAVE_ADDRESS_FAMILY ${HAVE_SIZEOF_ADDRESS_FAMILY})
|
||||
set(CMAKE_EXTRA_INCLUDE_FILES "")
|
||||
set(CMAKE_EXTRA_INCLUDE_FILES "winsock2.h")
|
||||
check_type_size("ADDRESS_FAMILY" SIZEOF_ADDRESS_FAMILY)
|
||||
set(HAVE_ADDRESS_FAMILY ${HAVE_SIZEOF_ADDRESS_FAMILY})
|
||||
set(CMAKE_EXTRA_INCLUDE_FILES "")
|
||||
endif()
|
||||
|
||||
# Do curl specific tests
|
||||
foreach(CURL_TEST
|
||||
foreach(_curl_test IN ITEMS
|
||||
HAVE_FCNTL_O_NONBLOCK
|
||||
HAVE_IOCTLSOCKET
|
||||
HAVE_IOCTLSOCKET_CAMEL
|
||||
@@ -1419,34 +1577,34 @@ foreach(CURL_TEST
|
||||
HAVE_FILE_OFFSET_BITS
|
||||
HAVE_ATOMIC
|
||||
)
|
||||
curl_internal_test(${CURL_TEST})
|
||||
curl_internal_test(${_curl_test})
|
||||
endforeach()
|
||||
|
||||
if(HAVE_FILE_OFFSET_BITS)
|
||||
set(_FILE_OFFSET_BITS 64)
|
||||
set(CMAKE_REQUIRED_FLAGS "-D_FILE_OFFSET_BITS=64")
|
||||
endif()
|
||||
check_type_size("off_t" SIZEOF_OFF_T)
|
||||
check_type_size("off_t" SIZEOF_OFF_T)
|
||||
|
||||
# fseeko may not exist with _FILE_OFFSET_BITS=64 but can exist with
|
||||
# _FILE_OFFSET_BITS unset or 32 (e.g. Android ARMv7 with NDK 26b and API level < 24)
|
||||
# so we need to test fseeko after testing for _FILE_OFFSET_BITS
|
||||
check_symbol_exists(fseeko "${CURL_INCLUDES};stdio.h" HAVE_FSEEKO)
|
||||
check_symbol_exists("fseeko" "${CURL_INCLUDES};stdio.h" HAVE_FSEEKO)
|
||||
|
||||
if(HAVE_FSEEKO)
|
||||
set(HAVE_DECL_FSEEKO 1)
|
||||
endif()
|
||||
|
||||
# include this header to get the type
|
||||
# Include this header to get the type
|
||||
set(CMAKE_REQUIRED_INCLUDES "${CURL_SOURCE_DIR}/include")
|
||||
set(CMAKE_EXTRA_INCLUDE_FILES "curl/system.h")
|
||||
check_type_size("curl_off_t" SIZEOF_CURL_OFF_T)
|
||||
check_type_size("curl_off_t" SIZEOF_CURL_OFF_T)
|
||||
set(CMAKE_EXTRA_INCLUDE_FILES "curl/curl.h")
|
||||
check_type_size("curl_socket_t" SIZEOF_CURL_SOCKET_T)
|
||||
check_type_size("curl_socket_t" SIZEOF_CURL_SOCKET_T)
|
||||
set(CMAKE_EXTRA_INCLUDE_FILES "")
|
||||
|
||||
if(NOT WIN32 AND NOT CMAKE_CROSSCOMPILING)
|
||||
# on not-Windows and not-crosscompiling, check for writable argv[]
|
||||
# On non-Windows and not cross-compiling, check for writable argv[]
|
||||
include(CheckCSourceRuns)
|
||||
check_c_source_runs("
|
||||
int main(int argc, char **argv)
|
||||
@@ -1457,45 +1615,45 @@ if(NOT WIN32 AND NOT CMAKE_CROSSCOMPILING)
|
||||
}" HAVE_WRITABLE_ARGV)
|
||||
endif()
|
||||
|
||||
set(CMAKE_REQUIRED_FLAGS)
|
||||
unset(CMAKE_REQUIRED_FLAGS)
|
||||
|
||||
option(ENABLE_WEBSOCKETS "Set to ON to enable EXPERIMENTAL websockets" OFF)
|
||||
option(ENABLE_WEBSOCKETS "Enable WebSockets (experimental)" OFF)
|
||||
|
||||
if(ENABLE_WEBSOCKETS)
|
||||
if(${SIZEOF_CURL_OFF_T} GREATER "4")
|
||||
if(SIZEOF_CURL_OFF_T GREATER 4)
|
||||
set(USE_WEBSOCKETS ON)
|
||||
else()
|
||||
message(WARNING "curl_off_t is too small to enable WebSockets")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
foreach(CURL_TEST
|
||||
foreach(_curl_test IN ITEMS
|
||||
HAVE_GLIBC_STRERROR_R
|
||||
HAVE_POSIX_STRERROR_R
|
||||
)
|
||||
curl_internal_test(${CURL_TEST})
|
||||
curl_internal_test(${_curl_test})
|
||||
endforeach()
|
||||
|
||||
# Check for reentrant
|
||||
foreach(CURL_TEST
|
||||
foreach(_curl_test IN ITEMS
|
||||
HAVE_GETHOSTBYNAME_R_3
|
||||
HAVE_GETHOSTBYNAME_R_5
|
||||
HAVE_GETHOSTBYNAME_R_6)
|
||||
if(NOT ${CURL_TEST})
|
||||
if(${CURL_TEST}_REENTRANT)
|
||||
if(NOT ${_curl_test})
|
||||
if(${_curl_test}_REENTRANT)
|
||||
set(NEED_REENTRANT 1)
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(NEED_REENTRANT)
|
||||
foreach(CURL_TEST
|
||||
foreach(_curl_test IN ITEMS
|
||||
HAVE_GETHOSTBYNAME_R_3
|
||||
HAVE_GETHOSTBYNAME_R_5
|
||||
HAVE_GETHOSTBYNAME_R_6)
|
||||
set(${CURL_TEST} 0)
|
||||
if(${CURL_TEST}_REENTRANT)
|
||||
set(${CURL_TEST} 1)
|
||||
set(${_curl_test} 0)
|
||||
if(${_curl_test}_REENTRANT)
|
||||
set(${_curl_test} 1)
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
@@ -1522,28 +1680,28 @@ if(HAVE_FIONBIO OR
|
||||
HAVE_IOCTLSOCKET OR
|
||||
HAVE_IOCTLSOCKET_CASE OR
|
||||
HAVE_O_NONBLOCK)
|
||||
set(HAVE_DISABLED_NONBLOCKING)
|
||||
unset(HAVE_DISABLED_NONBLOCKING)
|
||||
endif()
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCC AND APPLE)
|
||||
include(CheckCCompilerFlag)
|
||||
check_c_compiler_flag(-Wno-long-double HAVE_C_FLAG_Wno_long_double)
|
||||
check_c_compiler_flag("-Wno-long-double" HAVE_C_FLAG_Wno_long_double)
|
||||
if(HAVE_C_FLAG_Wno_long_double)
|
||||
# The Mac version of GCC warns about use of long double. Disable it.
|
||||
get_source_file_property(MPRINTF_COMPILE_FLAGS mprintf.c COMPILE_FLAGS)
|
||||
if(MPRINTF_COMPILE_FLAGS)
|
||||
set(MPRINTF_COMPILE_FLAGS "${MPRINTF_COMPILE_FLAGS} -Wno-long-double")
|
||||
get_source_file_property(_mprintf_compile_flags "mprintf.c" COMPILE_FLAGS)
|
||||
if(_mprintf_compile_flags)
|
||||
set(_mprintf_compile_flags "${_mprintf_compile_flags} -Wno-long-double")
|
||||
else()
|
||||
set(MPRINTF_COMPILE_FLAGS "-Wno-long-double")
|
||||
set(_mprintf_compile_flags "-Wno-long-double")
|
||||
endif()
|
||||
set_source_files_properties(mprintf.c PROPERTIES
|
||||
COMPILE_FLAGS ${MPRINTF_COMPILE_FLAGS})
|
||||
set_source_files_properties("mprintf.c" PROPERTIES
|
||||
COMPILE_FLAGS ${_mprintf_compile_flags})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include(CMake/OtherTests.cmake)
|
||||
|
||||
add_definitions(-DHAVE_CONFIG_H)
|
||||
add_definitions("-DHAVE_CONFIG_H")
|
||||
|
||||
# For Windows, all compilers used by CMake should support large files
|
||||
if(WIN32)
|
||||
@@ -1567,7 +1725,7 @@ if(MSVC)
|
||||
# Disable default manifest added by CMake
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /MANIFEST:NO")
|
||||
|
||||
add_definitions(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE)
|
||||
add_definitions("-D_CRT_SECURE_NO_DEPRECATE" "-D_CRT_NONSTDC_NO_DEPRECATE")
|
||||
if(CMAKE_C_FLAGS MATCHES "/W[0-4]")
|
||||
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
|
||||
else()
|
||||
@@ -1581,10 +1739,10 @@ if(MSVC)
|
||||
endif()
|
||||
|
||||
if(CURL_WERROR)
|
||||
if(MSVC_VERSION)
|
||||
if(MSVC)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX")
|
||||
else()
|
||||
# this assumes clang or gcc style options
|
||||
# This assumes clang or gcc style options
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
|
||||
endif()
|
||||
endif()
|
||||
@@ -1601,35 +1759,38 @@ if(CURL_LTO)
|
||||
if(CURL_HAS_LTO)
|
||||
message(STATUS "LTO supported and enabled")
|
||||
else()
|
||||
message(FATAL_ERROR "LTO was requested - but compiler doesn't support it\n${CURL_LTO_ERROR}")
|
||||
message(FATAL_ERROR "LTO was requested - but compiler does not support it\n${CURL_LTO_ERROR}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
# Ugly (but functional) way to include "Makefile.inc" by transforming it
|
||||
# (= regenerate it).
|
||||
function(transform_makefile_inc INPUT_FILE OUTPUT_FILE)
|
||||
file(READ ${INPUT_FILE} MAKEFILE_INC_TEXT)
|
||||
string(REPLACE "$(top_srcdir)" "\${CURL_SOURCE_DIR}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})
|
||||
string(REPLACE "$(top_builddir)" "\${CURL_BINARY_DIR}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})
|
||||
function(transform_makefile_inc _input_file _output_file)
|
||||
file(READ ${_input_file} _makefile_inc_text)
|
||||
string(REPLACE "$(top_srcdir)" "\${CURL_SOURCE_DIR}" _makefile_inc_text ${_makefile_inc_text})
|
||||
string(REPLACE "$(top_builddir)" "\${CURL_BINARY_DIR}" _makefile_inc_text ${_makefile_inc_text})
|
||||
|
||||
string(REGEX REPLACE "\\\\\n" "!π!α!" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})
|
||||
string(REGEX REPLACE "([a-zA-Z_][a-zA-Z0-9_]*)[\t ]*=[\t ]*([^\n]*)" "SET(\\1 \\2)" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})
|
||||
string(REPLACE "!π!α!" "\n" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})
|
||||
string(REGEX REPLACE "\\\\\n" "!π!α!" _makefile_inc_text ${_makefile_inc_text})
|
||||
string(REGEX REPLACE "([a-zA-Z_][a-zA-Z0-9_]*)[\t ]*=[\t ]*([^\n]*)" "set(\\1 \\2)" _makefile_inc_text ${_makefile_inc_text})
|
||||
string(REPLACE "!π!α!" "\n" _makefile_inc_text ${_makefile_inc_text})
|
||||
|
||||
string(REGEX REPLACE "\\$\\(([a-zA-Z_][a-zA-Z0-9_]*)\\)" "\${\\1}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) # Replace $() with ${}
|
||||
string(REGEX REPLACE "@([a-zA-Z_][a-zA-Z0-9_]*)@" "\${\\1}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) # Replace @@ with ${}, even if that may not be read by CMake scripts.
|
||||
file(WRITE ${OUTPUT_FILE} ${MAKEFILE_INC_TEXT})
|
||||
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${INPUT_FILE}")
|
||||
# Replace $() with ${}
|
||||
string(REGEX REPLACE "\\$\\(([a-zA-Z_][a-zA-Z0-9_]*)\\)" "\${\\1}" _makefile_inc_text ${_makefile_inc_text})
|
||||
# Replace @@ with ${}, even if that may not be read by CMake scripts.
|
||||
string(REGEX REPLACE "@([a-zA-Z_][a-zA-Z0-9_]*)@" "\${\\1}" _makefile_inc_text ${_makefile_inc_text})
|
||||
|
||||
file(WRITE ${_output_file} ${_makefile_inc_text})
|
||||
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${_input_file}")
|
||||
endfunction()
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
set(CURL_INSTALL_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME})
|
||||
set(CURL_INSTALL_CMAKE_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
|
||||
set(TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets")
|
||||
set(generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated")
|
||||
set(project_config "${generated_dir}/${PROJECT_NAME}Config.cmake")
|
||||
set(version_config "${generated_dir}/${PROJECT_NAME}ConfigVersion.cmake")
|
||||
set(_generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated")
|
||||
set(_project_config "${_generated_dir}/${PROJECT_NAME}Config.cmake")
|
||||
set(_version_config "${_generated_dir}/${PROJECT_NAME}ConfigVersion.cmake")
|
||||
|
||||
cmake_dependent_option(BUILD_TESTING "Build tests"
|
||||
ON "PERL_FOUND;NOT CURL_DISABLE_TESTS"
|
||||
@@ -1654,194 +1815,199 @@ if(BUILD_TESTING)
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
|
||||
if(NOT CURL_DISABLE_INSTALL)
|
||||
|
||||
install(FILES "${PROJECT_SOURCE_DIR}/scripts/mk-ca-bundle.pl"
|
||||
DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
PERMISSIONS
|
||||
OWNER_READ OWNER_WRITE OWNER_EXECUTE
|
||||
GROUP_READ GROUP_EXECUTE
|
||||
WORLD_READ WORLD_EXECUTE)
|
||||
|
||||
# Helper to populate a list (_items) with a label when conditions
|
||||
# (the remaining args) are satisfied
|
||||
macro(_add_if label)
|
||||
# needs to be a macro to allow this indirection
|
||||
if(${ARGN})
|
||||
set(_items ${_items} "${label}")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# NTLM support requires crypto functions from various SSL libs.
|
||||
# These conditions must match those in lib/curl_setup.h.
|
||||
if(NOT CURL_DISABLE_NTLM AND
|
||||
(USE_OPENSSL OR
|
||||
USE_MBEDTLS OR
|
||||
USE_GNUTLS OR
|
||||
USE_SECTRANSP OR
|
||||
USE_WIN32_CRYPTO OR
|
||||
(USE_WOLFSSL AND HAVE_WOLFSSL_DES_ECB_ENCRYPT)))
|
||||
set(use_curl_ntlm_core ON)
|
||||
# Helper to populate a list (_items) with a label when conditions
|
||||
# (the remaining args) are satisfied
|
||||
macro(_add_if _label)
|
||||
# Needs to be a macro to allow this indirection
|
||||
if(${ARGN})
|
||||
set(_items ${_items} "${_label}")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# Clear list and try to detect available protocols
|
||||
set(_items)
|
||||
_add_if("HTTP" NOT CURL_DISABLE_HTTP)
|
||||
_add_if("IPFS" NOT CURL_DISABLE_HTTP)
|
||||
_add_if("IPNS" NOT CURL_DISABLE_HTTP)
|
||||
_add_if("HTTPS" NOT CURL_DISABLE_HTTP AND SSL_ENABLED)
|
||||
_add_if("FTP" NOT CURL_DISABLE_FTP)
|
||||
_add_if("FTPS" NOT CURL_DISABLE_FTP AND SSL_ENABLED)
|
||||
_add_if("FILE" NOT CURL_DISABLE_FILE)
|
||||
_add_if("TELNET" NOT CURL_DISABLE_TELNET)
|
||||
_add_if("LDAP" NOT CURL_DISABLE_LDAP)
|
||||
# CURL_DISABLE_LDAP implies CURL_DISABLE_LDAPS
|
||||
_add_if("LDAPS" NOT CURL_DISABLE_LDAPS AND
|
||||
((USE_OPENLDAP AND SSL_ENABLED) OR
|
||||
(NOT USE_OPENLDAP AND HAVE_LDAP_SSL)))
|
||||
_add_if("DICT" NOT CURL_DISABLE_DICT)
|
||||
_add_if("TFTP" NOT CURL_DISABLE_TFTP)
|
||||
_add_if("GOPHER" NOT CURL_DISABLE_GOPHER)
|
||||
_add_if("GOPHERS" NOT CURL_DISABLE_GOPHER AND SSL_ENABLED)
|
||||
_add_if("POP3" NOT CURL_DISABLE_POP3)
|
||||
_add_if("POP3S" NOT CURL_DISABLE_POP3 AND SSL_ENABLED)
|
||||
_add_if("IMAP" NOT CURL_DISABLE_IMAP)
|
||||
_add_if("IMAPS" NOT CURL_DISABLE_IMAP AND SSL_ENABLED)
|
||||
_add_if("SMB" NOT CURL_DISABLE_SMB AND
|
||||
use_curl_ntlm_core AND (SIZEOF_CURL_OFF_T GREATER 4))
|
||||
_add_if("SMBS" NOT CURL_DISABLE_SMB AND SSL_ENABLED AND
|
||||
use_curl_ntlm_core AND (SIZEOF_CURL_OFF_T GREATER 4))
|
||||
_add_if("SMTP" NOT CURL_DISABLE_SMTP)
|
||||
_add_if("SMTPS" NOT CURL_DISABLE_SMTP AND SSL_ENABLED)
|
||||
_add_if("SCP" USE_LIBSSH2 OR USE_LIBSSH)
|
||||
_add_if("SFTP" USE_LIBSSH2 OR USE_LIBSSH)
|
||||
_add_if("RTSP" NOT CURL_DISABLE_RTSP)
|
||||
_add_if("RTMP" USE_LIBRTMP)
|
||||
_add_if("MQTT" NOT CURL_DISABLE_MQTT)
|
||||
_add_if("WS" USE_WEBSOCKETS)
|
||||
_add_if("WSS" USE_WEBSOCKETS AND SSL_ENABLED)
|
||||
if(_items)
|
||||
# NTLM support requires crypto functions from various SSL libs.
|
||||
# These conditions must match those in lib/curl_setup.h.
|
||||
if(NOT CURL_DISABLE_NTLM AND
|
||||
(USE_OPENSSL OR
|
||||
USE_MBEDTLS OR
|
||||
USE_GNUTLS OR
|
||||
USE_SECTRANSP OR
|
||||
USE_WIN32_CRYPTO OR
|
||||
(USE_WOLFSSL AND HAVE_WOLFSSL_DES_ECB_ENCRYPT)))
|
||||
set(_use_curl_ntlm_core ON)
|
||||
endif()
|
||||
|
||||
# Clear list and try to detect available protocols
|
||||
unset(_items)
|
||||
_add_if("HTTP" NOT CURL_DISABLE_HTTP)
|
||||
_add_if("IPFS" NOT CURL_DISABLE_HTTP)
|
||||
_add_if("IPNS" NOT CURL_DISABLE_HTTP)
|
||||
_add_if("HTTPS" NOT CURL_DISABLE_HTTP AND _ssl_enabled)
|
||||
_add_if("FTP" NOT CURL_DISABLE_FTP)
|
||||
_add_if("FTPS" NOT CURL_DISABLE_FTP AND _ssl_enabled)
|
||||
_add_if("FILE" NOT CURL_DISABLE_FILE)
|
||||
_add_if("TELNET" NOT CURL_DISABLE_TELNET)
|
||||
_add_if("LDAP" NOT CURL_DISABLE_LDAP)
|
||||
# CURL_DISABLE_LDAP implies CURL_DISABLE_LDAPS
|
||||
_add_if("LDAPS" NOT CURL_DISABLE_LDAPS AND
|
||||
((USE_OPENLDAP AND _ssl_enabled) OR
|
||||
(NOT USE_OPENLDAP AND HAVE_LDAP_SSL)))
|
||||
_add_if("DICT" NOT CURL_DISABLE_DICT)
|
||||
_add_if("TFTP" NOT CURL_DISABLE_TFTP)
|
||||
_add_if("GOPHER" NOT CURL_DISABLE_GOPHER)
|
||||
_add_if("GOPHERS" NOT CURL_DISABLE_GOPHER AND _ssl_enabled)
|
||||
_add_if("POP3" NOT CURL_DISABLE_POP3)
|
||||
_add_if("POP3S" NOT CURL_DISABLE_POP3 AND _ssl_enabled)
|
||||
_add_if("IMAP" NOT CURL_DISABLE_IMAP)
|
||||
_add_if("IMAPS" NOT CURL_DISABLE_IMAP AND _ssl_enabled)
|
||||
_add_if("SMB" NOT CURL_DISABLE_SMB AND
|
||||
_use_curl_ntlm_core AND (SIZEOF_CURL_OFF_T GREATER 4))
|
||||
_add_if("SMBS" NOT CURL_DISABLE_SMB AND _ssl_enabled AND
|
||||
_use_curl_ntlm_core AND (SIZEOF_CURL_OFF_T GREATER 4))
|
||||
_add_if("SMTP" NOT CURL_DISABLE_SMTP)
|
||||
_add_if("SMTPS" NOT CURL_DISABLE_SMTP AND _ssl_enabled)
|
||||
_add_if("SCP" USE_LIBSSH2 OR USE_LIBSSH OR USE_WOLFSSH)
|
||||
_add_if("SFTP" USE_LIBSSH2 OR USE_LIBSSH OR USE_WOLFSSH)
|
||||
_add_if("RTSP" NOT CURL_DISABLE_RTSP)
|
||||
_add_if("RTMP" USE_LIBRTMP)
|
||||
_add_if("MQTT" NOT CURL_DISABLE_MQTT)
|
||||
_add_if("WS" USE_WEBSOCKETS)
|
||||
_add_if("WSS" USE_WEBSOCKETS AND _ssl_enabled)
|
||||
if(_items)
|
||||
list(SORT _items)
|
||||
endif()
|
||||
string(REPLACE ";" " " SUPPORT_PROTOCOLS "${_items}")
|
||||
string(TOLOWER "${SUPPORT_PROTOCOLS}" _support_protocols_lower)
|
||||
message(STATUS "Protocols: ${_support_protocols_lower}")
|
||||
|
||||
# Clear list and try to detect available features
|
||||
unset(_items)
|
||||
_add_if("SSL" _ssl_enabled)
|
||||
_add_if("IPv6" ENABLE_IPV6)
|
||||
_add_if("UnixSockets" USE_UNIX_SOCKETS)
|
||||
_add_if("libz" HAVE_LIBZ)
|
||||
_add_if("brotli" HAVE_BROTLI)
|
||||
_add_if("gsasl" USE_GSASL)
|
||||
_add_if("zstd" HAVE_ZSTD)
|
||||
_add_if("AsynchDNS" USE_ARES OR USE_THREADS_POSIX OR USE_THREADS_WIN32)
|
||||
_add_if("IDN" (HAVE_LIBIDN2 AND HAVE_IDN2_H) OR
|
||||
USE_WIN32_IDN OR
|
||||
USE_APPLE_IDN)
|
||||
_add_if("Largefile" (SIZEOF_CURL_OFF_T GREATER 4) AND
|
||||
((SIZEOF_OFF_T GREATER 4) OR USE_WIN32_LARGE_FILES))
|
||||
_add_if("SSPI" USE_WINDOWS_SSPI)
|
||||
_add_if("GSS-API" HAVE_GSSAPI)
|
||||
_add_if("alt-svc" NOT CURL_DISABLE_ALTSVC)
|
||||
_add_if("HSTS" NOT CURL_DISABLE_HSTS)
|
||||
_add_if("SPNEGO" NOT CURL_DISABLE_NEGOTIATE_AUTH AND
|
||||
(HAVE_GSSAPI OR USE_WINDOWS_SSPI))
|
||||
_add_if("Kerberos" NOT CURL_DISABLE_KERBEROS_AUTH AND
|
||||
(HAVE_GSSAPI OR USE_WINDOWS_SSPI))
|
||||
_add_if("NTLM" NOT (CURL_DISABLE_NTLM) AND
|
||||
(_use_curl_ntlm_core OR USE_WINDOWS_SSPI))
|
||||
_add_if("TLS-SRP" USE_TLS_SRP)
|
||||
_add_if("HTTP2" USE_NGHTTP2)
|
||||
_add_if("HTTP3" USE_NGTCP2 OR USE_QUICHE OR USE_MSH3 OR USE_OPENSSL_QUIC)
|
||||
_add_if("MultiSSL" CURL_WITH_MULTI_SSL)
|
||||
_add_if("HTTPS-proxy" _ssl_enabled AND (USE_OPENSSL OR USE_GNUTLS
|
||||
OR USE_SCHANNEL OR USE_RUSTLS OR USE_BEARSSL OR
|
||||
USE_MBEDTLS OR USE_SECTRANSP OR
|
||||
(USE_WOLFSSL AND HAVE_WOLFSSL_FULL_BIO)))
|
||||
_add_if("Unicode" ENABLE_UNICODE)
|
||||
_add_if("threadsafe" HAVE_ATOMIC OR
|
||||
(USE_THREADS_POSIX AND HAVE_PTHREAD_H) OR
|
||||
(WIN32 AND HAVE_WIN32_WINNT GREATER_EQUAL 0x0600))
|
||||
_add_if("Debug" ENABLE_DEBUG)
|
||||
_add_if("TrackMemory" ENABLE_CURLDEBUG)
|
||||
_add_if("ECH" _ssl_enabled AND HAVE_ECH)
|
||||
_add_if("PSL" USE_LIBPSL)
|
||||
_add_if("CAcert" CURL_CA_EMBED_SET)
|
||||
if(_items)
|
||||
if(NOT CMAKE_VERSION VERSION_LESS 3.13)
|
||||
list(SORT _items CASE INSENSITIVE)
|
||||
else()
|
||||
list(SORT _items)
|
||||
endif()
|
||||
string(REPLACE ";" " " SUPPORT_PROTOCOLS "${_items}")
|
||||
string(TOLOWER "${SUPPORT_PROTOCOLS}" SUPPORT_PROTOCOLS_LOWER)
|
||||
message(STATUS "Protocols: ${SUPPORT_PROTOCOLS_LOWER}")
|
||||
endif()
|
||||
string(REPLACE ";" " " SUPPORT_FEATURES "${_items}")
|
||||
message(STATUS "Features: ${SUPPORT_FEATURES}")
|
||||
|
||||
# Clear list and try to detect available features
|
||||
set(_items)
|
||||
_add_if("SSL" SSL_ENABLED)
|
||||
_add_if("IPv6" ENABLE_IPV6)
|
||||
_add_if("UnixSockets" USE_UNIX_SOCKETS)
|
||||
_add_if("libz" HAVE_LIBZ)
|
||||
_add_if("brotli" HAVE_BROTLI)
|
||||
_add_if("gsasl" USE_GSASL)
|
||||
_add_if("zstd" HAVE_ZSTD)
|
||||
_add_if("AsynchDNS" USE_ARES OR USE_THREADS_POSIX OR USE_THREADS_WIN32)
|
||||
_add_if("IDN" (HAVE_LIBIDN2 AND HAVE_IDN2_H) OR
|
||||
USE_WIN32_IDN OR
|
||||
USE_APPLE_IDN)
|
||||
_add_if("Largefile" (SIZEOF_CURL_OFF_T GREATER 4) AND
|
||||
((SIZEOF_OFF_T GREATER 4) OR USE_WIN32_LARGE_FILES))
|
||||
_add_if("SSPI" USE_WINDOWS_SSPI)
|
||||
_add_if("GSS-API" HAVE_GSSAPI)
|
||||
_add_if("alt-svc" NOT CURL_DISABLE_ALTSVC)
|
||||
_add_if("HSTS" NOT CURL_DISABLE_HSTS)
|
||||
_add_if("SPNEGO" NOT CURL_DISABLE_NEGOTIATE_AUTH AND
|
||||
(HAVE_GSSAPI OR USE_WINDOWS_SSPI))
|
||||
_add_if("Kerberos" NOT CURL_DISABLE_KERBEROS_AUTH AND
|
||||
(HAVE_GSSAPI OR USE_WINDOWS_SSPI))
|
||||
_add_if("NTLM" NOT (CURL_DISABLE_NTLM) AND
|
||||
(use_curl_ntlm_core OR USE_WINDOWS_SSPI))
|
||||
_add_if("TLS-SRP" USE_TLS_SRP)
|
||||
_add_if("HTTP2" USE_NGHTTP2)
|
||||
_add_if("HTTP3" USE_NGTCP2 OR USE_QUICHE OR USE_OPENSSL_QUIC)
|
||||
_add_if("MultiSSL" CURL_WITH_MULTI_SSL)
|
||||
_add_if("HTTPS-proxy" SSL_ENABLED AND (USE_OPENSSL OR USE_GNUTLS
|
||||
OR USE_SCHANNEL OR USE_RUSTLS OR USE_BEARSSL OR
|
||||
USE_MBEDTLS OR USE_SECTRANSP OR
|
||||
(USE_WOLFSSL AND HAVE_WOLFSSL_FULL_BIO)))
|
||||
_add_if("Unicode" ENABLE_UNICODE)
|
||||
_add_if("threadsafe" HAVE_ATOMIC OR
|
||||
(USE_THREADS_POSIX AND HAVE_PTHREAD_H) OR
|
||||
(WIN32 AND HAVE_WIN32_WINNT GREATER_EQUAL 0x600))
|
||||
_add_if("Debug" ENABLE_DEBUG)
|
||||
_add_if("TrackMemory" ENABLE_CURLDEBUG)
|
||||
_add_if("ECH" SSL_ENABLED AND HAVE_ECH)
|
||||
_add_if("PSL" USE_LIBPSL)
|
||||
if(_items)
|
||||
if(NOT CMAKE_VERSION VERSION_LESS 3.13)
|
||||
list(SORT _items CASE INSENSITIVE)
|
||||
else()
|
||||
list(SORT _items)
|
||||
endif()
|
||||
endif()
|
||||
string(REPLACE ";" " " SUPPORT_FEATURES "${_items}")
|
||||
message(STATUS "Features: ${SUPPORT_FEATURES}")
|
||||
# Clear list and collect SSL backends
|
||||
unset(_items)
|
||||
_add_if("Schannel" _ssl_enabled AND USE_SCHANNEL)
|
||||
_add_if("OpenSSL" _ssl_enabled AND USE_OPENSSL AND OPENSSL_VERSION VERSION_LESS 3.0.0)
|
||||
_add_if("OpenSSL v3+" _ssl_enabled AND USE_OPENSSL AND NOT OPENSSL_VERSION VERSION_LESS 3.0.0)
|
||||
_add_if("Secure Transport" _ssl_enabled AND USE_SECTRANSP)
|
||||
_add_if("mbedTLS" _ssl_enabled AND USE_MBEDTLS)
|
||||
_add_if("BearSSL" _ssl_enabled AND USE_BEARSSL)
|
||||
_add_if("wolfSSL" _ssl_enabled AND USE_WOLFSSL)
|
||||
_add_if("GnuTLS" _ssl_enabled AND USE_GNUTLS)
|
||||
_add_if("rustls" _ssl_enabled AND USE_RUSTLS)
|
||||
|
||||
# Clear list and collect SSL backends
|
||||
set(_items)
|
||||
_add_if("Schannel" SSL_ENABLED AND USE_SCHANNEL)
|
||||
_add_if("OpenSSL" SSL_ENABLED AND USE_OPENSSL)
|
||||
_add_if("Secure Transport" SSL_ENABLED AND USE_SECTRANSP)
|
||||
_add_if("mbedTLS" SSL_ENABLED AND USE_MBEDTLS)
|
||||
_add_if("BearSSL" SSL_ENABLED AND USE_BEARSSL)
|
||||
_add_if("wolfSSL" SSL_ENABLED AND USE_WOLFSSL)
|
||||
_add_if("GnuTLS" SSL_ENABLED AND USE_GNUTLS)
|
||||
if(_items)
|
||||
if(NOT CMAKE_VERSION VERSION_LESS 3.13)
|
||||
list(SORT _items CASE INSENSITIVE)
|
||||
else()
|
||||
list(SORT _items)
|
||||
endif()
|
||||
endif()
|
||||
string(REPLACE ";" " " SSL_BACKENDS "${_items}")
|
||||
message(STATUS "Enabled SSL backends: ${SSL_BACKENDS}")
|
||||
if(CURL_DEFAULT_SSL_BACKEND)
|
||||
message(STATUS "Default SSL backend: ${CURL_DEFAULT_SSL_BACKEND}")
|
||||
endif()
|
||||
|
||||
if(_items)
|
||||
if(NOT CMAKE_VERSION VERSION_LESS 3.13)
|
||||
list(SORT _items CASE INSENSITIVE)
|
||||
else()
|
||||
list(SORT _items)
|
||||
endif()
|
||||
endif()
|
||||
string(REPLACE ";" " " SSL_BACKENDS "${_items}")
|
||||
message(STATUS "Enabled SSL backends: ${SSL_BACKENDS}")
|
||||
if(CURL_DEFAULT_SSL_BACKEND)
|
||||
message(STATUS "Default SSL backend: ${CURL_DEFAULT_SSL_BACKEND}")
|
||||
endif()
|
||||
if(NOT CURL_DISABLE_INSTALL)
|
||||
|
||||
# curl-config needs the following options to be set.
|
||||
set(CC "${CMAKE_C_COMPILER}")
|
||||
# TODO probably put a -D... options here?
|
||||
# TODO: probably put a -D... options here?
|
||||
set(CONFIGURE_OPTIONS "")
|
||||
set(CURLVERSION "${CURL_VERSION}")
|
||||
set(VERSIONNUM "${CURL_VERSION_NUM}")
|
||||
set(prefix "${CMAKE_INSTALL_PREFIX}")
|
||||
set(exec_prefix "\${prefix}")
|
||||
set(includedir "\${prefix}/include")
|
||||
set(LDFLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
|
||||
set(LIBCURL_LIBS "")
|
||||
set(libdir "${CMAKE_INSTALL_PREFIX}/lib")
|
||||
# "a" (Linux) or "lib" (Windows)
|
||||
string(REPLACE "." "" libext "${CMAKE_STATIC_LIBRARY_SUFFIX}")
|
||||
|
||||
# For processing full path libraries into -L and -l ld options,
|
||||
# the directories that go with the -L option are cached, so they
|
||||
# only get added once per such directory.
|
||||
set(_libcurl_libs_dirs)
|
||||
# To avoid getting unnecessary -L options for known system directories,
|
||||
# _libcurl_libs_dirs is seeded with them.
|
||||
foreach(_libdir ${CMAKE_SYSTEM_PREFIX_PATH})
|
||||
set(_ldflags "")
|
||||
set(LIBCURL_PC_LIBS_PRIVATE "")
|
||||
|
||||
# Avoid getting unnecessary -L options for known system directories.
|
||||
unset(_sys_libdirs)
|
||||
foreach(_libdir IN LISTS CMAKE_SYSTEM_PREFIX_PATH)
|
||||
if(_libdir MATCHES "/$")
|
||||
set(_libdir "${_libdir}lib")
|
||||
else()
|
||||
set(_libdir "${_libdir}/lib")
|
||||
endif()
|
||||
if(IS_DIRECTORY "${_libdir}")
|
||||
list(APPEND _libcurl_libs_dirs "${_libdir}")
|
||||
list(APPEND _sys_libdirs "${_libdir}")
|
||||
endif()
|
||||
if(DEFINED CMAKE_LIBRARY_ARCHITECTURE)
|
||||
set(_libdir "${_libdir}/${CMAKE_LIBRARY_ARCHITECTURE}")
|
||||
if(IS_DIRECTORY "${_libdir}")
|
||||
list(APPEND _libcurl_libs_dirs "${_libdir}")
|
||||
list(APPEND _sys_libdirs "${_libdir}")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
foreach(_lib ${CMAKE_C_IMPLICIT_LINK_LIBRARIES} ${CURL_LIBS})
|
||||
foreach(_libdir IN LISTS CURL_LIBDIRS)
|
||||
list(FIND _sys_libdirs "${_libdir}" _libdir_index)
|
||||
if(_libdir_index LESS 0)
|
||||
list(APPEND _ldflags "-L${_libdir}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
foreach(_lib IN LISTS CMAKE_C_IMPLICIT_LINK_LIBRARIES CURL_LIBS)
|
||||
if(TARGET "${_lib}")
|
||||
set(_libname "${_lib}")
|
||||
get_target_property(_imported "${_libname}" IMPORTED)
|
||||
if(NOT _imported)
|
||||
# Reading the LOCATION property on non-imported target will error out.
|
||||
# Assume the user won't need this information in the .pc file.
|
||||
# Assume the user will not need this information in the .pc file.
|
||||
continue()
|
||||
endif()
|
||||
get_target_property(_lib "${_libname}" LOCATION)
|
||||
@@ -1850,137 +2016,172 @@ if(NOT CURL_DISABLE_INSTALL)
|
||||
continue()
|
||||
endif()
|
||||
endif()
|
||||
if(_lib MATCHES "^-")
|
||||
set(LIBCURL_LIBS "${LIBCURL_LIBS} ${_lib}")
|
||||
if(_lib MATCHES "^-") # '-framework <name>'
|
||||
list(APPEND _ldflags "${_lib}")
|
||||
elseif(_lib MATCHES ".*/.*")
|
||||
# This gets a bit more complex, because we want to specify the
|
||||
# directory separately, and only once per directory
|
||||
string(REGEX REPLACE "^(.*)/[^/]*$" "\\1" _libdir "${_lib}")
|
||||
string(REGEX REPLACE "^.*/([^/.]*).*$" "\\1" _libname "${_lib}")
|
||||
get_filename_component(_libdir ${_lib} DIRECTORY)
|
||||
get_filename_component(_libname ${_lib} NAME_WE)
|
||||
if(_libname MATCHES "^lib")
|
||||
list(FIND _libcurl_libs_dirs "${_libdir}" _libdir_index)
|
||||
list(FIND _sys_libdirs "${_libdir}" _libdir_index)
|
||||
if(_libdir_index LESS 0)
|
||||
list(APPEND _libcurl_libs_dirs "${_libdir}")
|
||||
set(LIBCURL_LIBS "${LIBCURL_LIBS} -L${_libdir}")
|
||||
list(APPEND _ldflags "-L${_libdir}")
|
||||
endif()
|
||||
string(REGEX REPLACE "^lib" "" _libname "${_libname}")
|
||||
set(LIBCURL_LIBS "${LIBCURL_LIBS} -l${_libname}")
|
||||
list(APPEND LIBCURL_PC_LIBS_PRIVATE "-l${_libname}")
|
||||
else()
|
||||
set(LIBCURL_LIBS "${LIBCURL_LIBS} ${_lib}")
|
||||
list(APPEND LIBCURL_PC_LIBS_PRIVATE "${_lib}")
|
||||
endif()
|
||||
else()
|
||||
set(LIBCURL_LIBS "${LIBCURL_LIBS} -l${_lib}")
|
||||
list(APPEND LIBCURL_PC_LIBS_PRIVATE "-l${_lib}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Export a .pc file for client projects not using CMake
|
||||
if(LIBCURL_PC_REQUIRES_PRIVATE)
|
||||
string(REPLACE ";" "," LIBCURL_PC_REQUIRES_PRIVATE "${LIBCURL_PC_REQUIRES_PRIVATE}")
|
||||
endif()
|
||||
if(LIBCURL_PC_LIBS_PRIVATE)
|
||||
string(REPLACE ";" " " LIBCURL_PC_LIBS_PRIVATE "${LIBCURL_PC_LIBS_PRIVATE}")
|
||||
endif()
|
||||
if(_ldflags)
|
||||
list(REMOVE_DUPLICATES _ldflags)
|
||||
string(REPLACE ";" " " _ldflags "${_ldflags}")
|
||||
set(LIBCURL_PC_LIBS_PRIVATE "${_ldflags} ${LIBCURL_PC_LIBS_PRIVATE}")
|
||||
string(STRIP "${LIBCURL_PC_LIBS_PRIVATE}" LIBCURL_PC_LIBS_PRIVATE)
|
||||
endif()
|
||||
set(LIBCURL_PC_CFLAGS_PRIVATE "-DCURL_STATICLIB")
|
||||
|
||||
# Merge pkg-config private fields into public ones when static-only
|
||||
if(BUILD_SHARED_LIBS)
|
||||
set(ENABLE_SHARED "yes")
|
||||
set(LIBCURL_PC_REQUIRES "")
|
||||
set(LIBCURL_NO_SHARED "")
|
||||
set(CPPFLAG_CURL_STATICLIB "")
|
||||
set(ENABLE_SHARED "yes")
|
||||
set(LIBCURL_PC_REQUIRES "")
|
||||
set(LIBCURL_PC_LIBS "")
|
||||
set(LIBCURL_PC_CFLAGS "")
|
||||
else()
|
||||
set(ENABLE_SHARED "no")
|
||||
set(LIBCURL_PC_REQUIRES "${LIBCURL_PC_REQUIRES_PRIVATE}")
|
||||
set(LIBCURL_NO_SHARED "${LIBCURL_LIBS}")
|
||||
set(CPPFLAG_CURL_STATICLIB "-DCURL_STATICLIB")
|
||||
set(ENABLE_SHARED "no")
|
||||
set(LIBCURL_PC_REQUIRES "${LIBCURL_PC_REQUIRES_PRIVATE}")
|
||||
set(LIBCURL_PC_LIBS "${LIBCURL_PC_LIBS_PRIVATE}")
|
||||
set(LIBCURL_PC_CFLAGS "${LIBCURL_PC_CFLAGS_PRIVATE}")
|
||||
endif()
|
||||
if(BUILD_STATIC_LIBS)
|
||||
set(ENABLE_STATIC "yes")
|
||||
set(ENABLE_STATIC "yes")
|
||||
else()
|
||||
set(ENABLE_STATIC "no")
|
||||
set(ENABLE_STATIC "no")
|
||||
endif()
|
||||
# "a" (Linux) or "lib" (Windows)
|
||||
string(REPLACE "." "" libext "${CMAKE_STATIC_LIBRARY_SUFFIX}")
|
||||
set(prefix "${CMAKE_INSTALL_PREFIX}")
|
||||
# Set this to "yes" to append all libraries on which -lcurl is dependent
|
||||
set(REQUIRE_LIB_DEPS "no")
|
||||
# SUPPORT_FEATURES
|
||||
# SUPPORT_PROTOCOLS
|
||||
set(VERSIONNUM "${CURL_VERSION_NUM}")
|
||||
|
||||
# Finally generate a "curl-config" matching this config
|
||||
# Use:
|
||||
# * ENABLE_SHARED
|
||||
# * ENABLE_STATIC
|
||||
configure_file("${CURL_SOURCE_DIR}/curl-config.in"
|
||||
"${CURL_BINARY_DIR}/curl-config" @ONLY)
|
||||
# Finally generate a "curl-config" matching this config.
|
||||
# Consumed variables:
|
||||
# CC
|
||||
# CONFIGURE_OPTIONS
|
||||
# CURLVERSION
|
||||
# CURL_CA_BUNDLE
|
||||
# ENABLE_SHARED
|
||||
# ENABLE_STATIC
|
||||
# exec_prefix
|
||||
# includedir
|
||||
# LDFLAGS
|
||||
# LIBCURL_PC_CFLAGS
|
||||
# LIBCURL_PC_LIBS_PRIVATE
|
||||
# libdir
|
||||
# libext
|
||||
# prefix
|
||||
# SSL_BACKENDS
|
||||
# SUPPORT_FEATURES
|
||||
# SUPPORT_PROTOCOLS
|
||||
# VERSIONNUM
|
||||
configure_file(
|
||||
"${CURL_SOURCE_DIR}/curl-config.in"
|
||||
"${CURL_BINARY_DIR}/curl-config" @ONLY)
|
||||
install(FILES "${CURL_BINARY_DIR}/curl-config"
|
||||
DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
PERMISSIONS
|
||||
OWNER_READ OWNER_WRITE OWNER_EXECUTE
|
||||
GROUP_READ GROUP_EXECUTE
|
||||
WORLD_READ WORLD_EXECUTE)
|
||||
DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
PERMISSIONS
|
||||
OWNER_READ OWNER_WRITE OWNER_EXECUTE
|
||||
GROUP_READ GROUP_EXECUTE
|
||||
WORLD_READ WORLD_EXECUTE)
|
||||
|
||||
# Finally generate a pkg-config file matching this config
|
||||
configure_file("${CURL_SOURCE_DIR}/libcurl.pc.in"
|
||||
"${CURL_BINARY_DIR}/libcurl.pc" @ONLY)
|
||||
# Consumed variables:
|
||||
# CURLVERSION
|
||||
# exec_prefix
|
||||
# includedir
|
||||
# LIBCURL_PC_CFLAGS
|
||||
# LIBCURL_PC_CFLAGS_PRIVATE
|
||||
# LIBCURL_PC_LIBS
|
||||
# LIBCURL_PC_LIBS_PRIVATE
|
||||
# LIBCURL_PC_REQUIRES
|
||||
# LIBCURL_PC_REQUIRES_PRIVATE
|
||||
# libdir
|
||||
# prefix
|
||||
# SUPPORT_FEATURES
|
||||
# SUPPORT_PROTOCOLS
|
||||
configure_file(
|
||||
"${CURL_SOURCE_DIR}/libcurl.pc.in"
|
||||
"${CURL_BINARY_DIR}/libcurl.pc" @ONLY)
|
||||
install(FILES "${CURL_BINARY_DIR}/libcurl.pc"
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
||||
|
||||
# install headers
|
||||
# Install headers
|
||||
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/curl"
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
FILES_MATCHING PATTERN "*.h")
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
FILES_MATCHING PATTERN "*.h")
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
write_basic_package_version_file(
|
||||
"${version_config}"
|
||||
VERSION ${CURL_VERSION}
|
||||
COMPATIBILITY SameMajorVersion
|
||||
)
|
||||
file(READ "${version_config}" generated_version_config)
|
||||
file(WRITE "${version_config}" "
|
||||
if(NOT PACKAGE_FIND_VERSION_RANGE AND PACKAGE_FIND_VERSION_MAJOR STREQUAL \"7\")
|
||||
# Version 8 satisfies version 7... requirements
|
||||
set(PACKAGE_FIND_VERSION_MAJOR 8)
|
||||
set(PACKAGE_FIND_VERSION_COUNT 1)
|
||||
endif()
|
||||
${generated_version_config}"
|
||||
)
|
||||
"${_version_config}"
|
||||
VERSION ${CURL_VERSION}
|
||||
COMPATIBILITY SameMajorVersion)
|
||||
file(READ "${_version_config}" _generated_version_config)
|
||||
file(WRITE "${_version_config}" "
|
||||
if(NOT PACKAGE_FIND_VERSION_RANGE AND PACKAGE_FIND_VERSION_MAJOR STREQUAL \"7\")
|
||||
# Version 8 satisfies version 7... requirements
|
||||
set(PACKAGE_FIND_VERSION_MAJOR 8)
|
||||
set(PACKAGE_FIND_VERSION_COUNT 1)
|
||||
endif()
|
||||
${_generated_version_config}")
|
||||
|
||||
# Use:
|
||||
# * TARGETS_EXPORT_NAME
|
||||
# * PROJECT_NAME
|
||||
configure_package_config_file(CMake/curl-config.cmake.in
|
||||
"${project_config}"
|
||||
# Consumed custom variables:
|
||||
# LIB_SELECTED
|
||||
# TARGETS_EXPORT_NAME
|
||||
# USE_OPENSSL
|
||||
# USE_ZLIB
|
||||
configure_package_config_file("CMake/curl-config.cmake.in"
|
||||
"${_project_config}"
|
||||
INSTALL_DESTINATION ${CURL_INSTALL_CMAKE_DIR}
|
||||
PATH_VARS CMAKE_INSTALL_INCLUDEDIR
|
||||
)
|
||||
PATH_VARS CMAKE_INSTALL_INCLUDEDIR)
|
||||
|
||||
if(CURL_ENABLE_EXPORT_TARGET)
|
||||
install(EXPORT "${TARGETS_EXPORT_NAME}"
|
||||
NAMESPACE "${PROJECT_NAME}::"
|
||||
DESTINATION ${CURL_INSTALL_CMAKE_DIR}
|
||||
)
|
||||
NAMESPACE "${PROJECT_NAME}::"
|
||||
DESTINATION ${CURL_INSTALL_CMAKE_DIR})
|
||||
endif()
|
||||
|
||||
install(FILES ${version_config} ${project_config}
|
||||
DESTINATION ${CURL_INSTALL_CMAKE_DIR}
|
||||
)
|
||||
install(FILES ${_version_config} ${_project_config}
|
||||
DESTINATION ${CURL_INSTALL_CMAKE_DIR})
|
||||
|
||||
# Workaround for MSVS10 to avoid the Dialog Hell
|
||||
# FIXME: This could be removed with future version of CMake.
|
||||
if(MSVC_VERSION EQUAL 1600)
|
||||
set(CURL_SLN_FILENAME "${CMAKE_CURRENT_BINARY_DIR}/CURL.sln")
|
||||
if(EXISTS "${CURL_SLN_FILENAME}")
|
||||
file(APPEND "${CURL_SLN_FILENAME}" "\n# This should be regenerated!\n")
|
||||
set(_curl_sln_filename "${CMAKE_CURRENT_BINARY_DIR}/CURL.sln")
|
||||
if(EXISTS "${_curl_sln_filename}")
|
||||
file(APPEND "${_curl_sln_filename}" "\n# This should be regenerated!\n")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT TARGET curl_uninstall)
|
||||
configure_file(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CMake/cmake_uninstall.cmake.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/CMake/cmake_uninstall.cmake
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/CMake/cmake_uninstall.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/CMake/cmake_uninstall.cmake"
|
||||
IMMEDIATE @ONLY)
|
||||
|
||||
add_custom_target(curl_uninstall
|
||||
COMMAND ${CMAKE_COMMAND} -P
|
||||
${CMAKE_CURRENT_BINARY_DIR}/CMake/cmake_uninstall.cmake)
|
||||
COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_BINARY_DIR}/CMake/cmake_uninstall.cmake")
|
||||
endif()
|
||||
|
||||
install(FILES "${PROJECT_SOURCE_DIR}/scripts/mk-ca-bundle.pl"
|
||||
DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
PERMISSIONS
|
||||
OWNER_READ OWNER_WRITE OWNER_EXECUTE
|
||||
GROUP_READ GROUP_EXECUTE
|
||||
WORLD_READ WORLD_EXECUTE)
|
||||
endif()
|
||||
|
||||
+13
-11
@@ -76,7 +76,7 @@
|
||||
#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__)
|
||||
#if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H) || \
|
||||
defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H))
|
||||
/* The check above prevents the winsock2 inclusion if winsock.h already was
|
||||
/* The check above prevents the winsock2.h inclusion if winsock.h already was
|
||||
included, since they cannot co-exist without problems */
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
@@ -721,6 +721,8 @@ typedef enum {
|
||||
with them. */
|
||||
#define CURLOPT_WRITEINFO CURLOPT_OBSOLETE40
|
||||
#define CURLOPT_CLOSEPOLICY CURLOPT_OBSOLETE72
|
||||
#define CURLOPT_OBSOLETE72 9999
|
||||
#define CURLOPT_OBSOLETE40 9999
|
||||
|
||||
#endif /* !CURL_NO_OLDIES */
|
||||
|
||||
@@ -1250,8 +1252,7 @@ typedef enum {
|
||||
/* send linked-list of post-transfer QUOTE commands */
|
||||
CURLOPT(CURLOPT_POSTQUOTE, CURLOPTTYPE_SLISTPOINT, 39),
|
||||
|
||||
/* OBSOLETE, do not use! */
|
||||
CURLOPT(CURLOPT_OBSOLETE40, CURLOPTTYPE_OBJECTPOINT, 40),
|
||||
/* 40 is not used */
|
||||
|
||||
/* talk a lot */
|
||||
CURLOPT(CURLOPT_VERBOSE, CURLOPTTYPE_LONG, 41),
|
||||
@@ -1352,9 +1353,7 @@ typedef enum {
|
||||
/* Max amount of cached alive connections */
|
||||
CURLOPT(CURLOPT_MAXCONNECTS, CURLOPTTYPE_LONG, 71),
|
||||
|
||||
/* OBSOLETE, do not use! */
|
||||
CURLOPT(CURLOPT_OBSOLETE72, CURLOPTTYPE_LONG, 72),
|
||||
|
||||
/* 72 = OBSOLETE */
|
||||
/* 73 = OBSOLETE */
|
||||
|
||||
/* Set to explicitly use a new connection for the upcoming transfer.
|
||||
@@ -1398,7 +1397,7 @@ typedef enum {
|
||||
operation. Set filename to "-" (dash) to make it go to stdout. */
|
||||
CURLOPT(CURLOPT_COOKIEJAR, CURLOPTTYPE_STRINGPOINT, 82),
|
||||
|
||||
/* Specify which SSL ciphers to use */
|
||||
/* Specify which TLS 1.2 (1.1, 1.0) ciphers to use */
|
||||
CURLOPT(CURLOPT_SSL_CIPHER_LIST, CURLOPTTYPE_STRINGPOINT, 83),
|
||||
|
||||
/* Specify which HTTP version to use! This must be set to one of the
|
||||
@@ -2022,7 +2021,7 @@ typedef enum {
|
||||
/* password for the SSL private key for proxy */
|
||||
CURLOPT(CURLOPT_PROXY_KEYPASSWD, CURLOPTTYPE_STRINGPOINT, 258),
|
||||
|
||||
/* Specify which SSL ciphers to use for proxy */
|
||||
/* Specify which TLS 1.2 (1.1, 1.0) ciphers to use for proxy */
|
||||
CURLOPT(CURLOPT_PROXY_SSL_CIPHER_LIST, CURLOPTTYPE_STRINGPOINT, 259),
|
||||
|
||||
/* CRL file for proxy */
|
||||
@@ -2203,7 +2202,7 @@ typedef enum {
|
||||
/* specify which protocols that libcurl is allowed to follow directs to */
|
||||
CURLOPT(CURLOPT_REDIR_PROTOCOLS_STR, CURLOPTTYPE_STRINGPOINT, 319),
|
||||
|
||||
/* websockets options */
|
||||
/* WebSockets options */
|
||||
CURLOPT(CURLOPT_WS_OPTIONS, CURLOPTTYPE_LONG, 320),
|
||||
|
||||
/* CA cache timeout */
|
||||
@@ -2645,7 +2644,7 @@ CURL_EXTERN char *curl_getenv(const char *variable);
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Returns a static ascii string of the libcurl version.
|
||||
* Returns a static ASCII string of the libcurl version.
|
||||
*/
|
||||
CURL_EXTERN char *curl_version(void);
|
||||
|
||||
@@ -2953,7 +2952,8 @@ typedef enum {
|
||||
CURLINFO_CONN_ID = CURLINFO_OFF_T + 64,
|
||||
CURLINFO_QUEUE_TIME_T = CURLINFO_OFF_T + 65,
|
||||
CURLINFO_USED_PROXY = CURLINFO_LONG + 66,
|
||||
CURLINFO_LASTONE = 66
|
||||
CURLINFO_POSTTRANSFER_TIME_T = CURLINFO_OFF_T + 67,
|
||||
CURLINFO_LASTONE = 67
|
||||
} CURLINFO;
|
||||
|
||||
/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
|
||||
@@ -3236,7 +3236,9 @@ CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask);
|
||||
#include "options.h"
|
||||
#include "header.h"
|
||||
#include "websockets.h"
|
||||
#ifndef CURL_SKIP_INCLUDE_MPRINTF
|
||||
#include "mprintf.h"
|
||||
#endif
|
||||
|
||||
/* the typechecker does not work in C++ (yet) */
|
||||
#if defined(__GNUC__) && defined(__GNUC_MINOR__) && \
|
||||
|
||||
@@ -32,12 +32,12 @@
|
||||
|
||||
/* This is the version number of the libcurl package from which this header
|
||||
file origins: */
|
||||
#define LIBCURL_VERSION "8.9.1-DEV"
|
||||
#define LIBCURL_VERSION "8.10.1-DEV"
|
||||
|
||||
/* The numeric version number is also available "in parts" by using these
|
||||
defines: */
|
||||
#define LIBCURL_VERSION_MAJOR 8
|
||||
#define LIBCURL_VERSION_MINOR 9
|
||||
#define LIBCURL_VERSION_MINOR 10
|
||||
#define LIBCURL_VERSION_PATCH 1
|
||||
|
||||
/* This is the numeric version of the libcurl version number, meant for easier
|
||||
@@ -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 0x080901
|
||||
#define LIBCURL_VERSION_NUM 0x080a01
|
||||
|
||||
/*
|
||||
* This is the date and time when the full source package was created. The
|
||||
|
||||
@@ -32,13 +32,18 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef CURL_TEMP_PRINTF
|
||||
#if (defined(__GNUC__) || defined(__clang__) || \
|
||||
defined(__IAR_SYSTEMS_ICC__)) && \
|
||||
defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
|
||||
!defined(CURL_NO_FMT_CHECKS)
|
||||
#if defined(__MINGW32__) && !defined(__clang__)
|
||||
#if defined(__MINGW_PRINTF_FORMAT) /* mingw-w64 3.0.0+. Needs stdio.h. */
|
||||
#define CURL_TEMP_PRINTF(fmt, arg) \
|
||||
__attribute__((format(gnu_printf, fmt, arg)))
|
||||
__attribute__((format(__MINGW_PRINTF_FORMAT, fmt, arg)))
|
||||
#else
|
||||
#define CURL_TEMP_PRINTF(fmt, arg)
|
||||
#endif
|
||||
#else
|
||||
#define CURL_TEMP_PRINTF(fmt, arg) \
|
||||
__attribute__((format(printf, fmt, arg)))
|
||||
@@ -46,6 +51,7 @@ extern "C" {
|
||||
#else
|
||||
#define CURL_TEMP_PRINTF(fmt, arg)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
CURL_EXTERN int curl_mprintf(const char *format, ...)
|
||||
CURL_TEMP_PRINTF(1, 2);
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
* changed.
|
||||
*
|
||||
* In order to differentiate between platforms/compilers/architectures use
|
||||
* only compiler built in predefined preprocessor symbols.
|
||||
* only compiler built-in predefined preprocessor symbols.
|
||||
*
|
||||
* curl_off_t
|
||||
* ----------
|
||||
|
||||
+85
-47
@@ -23,46 +23,44 @@
|
||||
###########################################################################
|
||||
set(LIB_NAME libcurl)
|
||||
set(LIBCURL_OUTPUT_NAME libcurl CACHE STRING "Basename of the curl library")
|
||||
add_definitions(-DBUILDING_LIBCURL)
|
||||
add_definitions("-DBUILDING_LIBCURL")
|
||||
|
||||
configure_file(curl_config.h.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/curl_config.h)
|
||||
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")
|
||||
include(${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake)
|
||||
include("${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake")
|
||||
|
||||
# DllMain is added later for DLL builds only.
|
||||
list(REMOVE_ITEM CSOURCES dllmain.c)
|
||||
list(REMOVE_ITEM CSOURCES "dllmain.c")
|
||||
|
||||
list(APPEND HHEADERS ${CMAKE_CURRENT_BINARY_DIR}/curl_config.h)
|
||||
list(APPEND HHEADERS "${CMAKE_CURRENT_BINARY_DIR}/curl_config.h")
|
||||
|
||||
# The rest of the build
|
||||
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR}/../include)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include)
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR}/..)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
include_directories(
|
||||
"${CMAKE_CURRENT_BINARY_DIR}"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
)
|
||||
if(USE_ARES)
|
||||
include_directories(${CARES_INCLUDE_DIR})
|
||||
include_directories(${CARES_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
if(BUILD_TESTING)
|
||||
add_library(
|
||||
curlu # special libcurlu library just for unittests
|
||||
curlu # special libcurlu library just for unittests
|
||||
STATIC
|
||||
EXCLUDE_FROM_ALL
|
||||
${HHEADERS} ${CSOURCES}
|
||||
)
|
||||
target_compile_definitions(curlu PUBLIC UNITTESTS CURL_STATICLIB)
|
||||
target_compile_definitions(curlu PUBLIC "UNITTESTS" "CURL_STATICLIB")
|
||||
target_link_libraries(curlu PRIVATE ${CURL_LIBS})
|
||||
endif()
|
||||
|
||||
if(ENABLE_CURLDEBUG)
|
||||
# We must compile these sources separately to avoid memdebug.h redefinitions
|
||||
# applying to them.
|
||||
set_source_files_properties(memdebug.c curl_multibyte.c PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON)
|
||||
set_source_files_properties("memdebug.c" "curl_multibyte.c" PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON)
|
||||
endif()
|
||||
|
||||
## Library definition
|
||||
@@ -97,13 +95,12 @@ if(SHARE_LIB_OBJECT)
|
||||
# exported libcurl symbols. We handle exports via libcurl.def instead.
|
||||
# Except with symbol hiding disabled or debug mode enabled, when we export
|
||||
# _all_ symbols from libcurl DLL, without using libcurl.def.
|
||||
set_property(TARGET ${LIB_OBJECT} APPEND
|
||||
PROPERTY COMPILE_DEFINITIONS "CURL_STATICLIB")
|
||||
set_property(TARGET ${LIB_OBJECT} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_STATICLIB")
|
||||
endif()
|
||||
target_link_libraries(${LIB_OBJECT} PRIVATE ${CURL_LIBS})
|
||||
set_target_properties(${LIB_OBJECT} PROPERTIES
|
||||
POSITION_INDEPENDENT_CODE ON)
|
||||
if(HIDES_CURL_PRIVATE_SYMBOLS)
|
||||
if(CURL_HIDES_PRIVATE_SYMBOLS)
|
||||
set_property(TARGET ${LIB_OBJECT} APPEND PROPERTY COMPILE_FLAGS "${CURL_CFLAG_SYMBOLS_HIDE}")
|
||||
set_property(TARGET ${LIB_OBJECT} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS")
|
||||
endif()
|
||||
@@ -114,22 +111,21 @@ if(SHARE_LIB_OBJECT)
|
||||
endif()
|
||||
|
||||
target_include_directories(${LIB_OBJECT} INTERFACE
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
$<BUILD_INTERFACE:${CURL_SOURCE_DIR}/include>)
|
||||
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
|
||||
"$<BUILD_INTERFACE:${CURL_SOURCE_DIR}/include>")
|
||||
|
||||
set(LIB_SOURCE $<TARGET_OBJECTS:${LIB_OBJECT}>)
|
||||
else()
|
||||
set(LIB_SOURCE ${HHEADERS} ${CSOURCES})
|
||||
endif()
|
||||
|
||||
# we want it to be called libcurl on all platforms
|
||||
# We want it to be called libcurl on all platforms
|
||||
if(BUILD_STATIC_LIBS)
|
||||
list(APPEND libcurl_export ${LIB_STATIC})
|
||||
add_library(${LIB_STATIC} STATIC ${LIB_SOURCE})
|
||||
add_library(${PROJECT_NAME}::${LIB_STATIC} ALIAS ${LIB_STATIC})
|
||||
if(WIN32)
|
||||
set_property(TARGET ${LIB_OBJECT} APPEND
|
||||
PROPERTY COMPILE_DEFINITIONS "CURL_STATICLIB")
|
||||
set_property(TARGET ${LIB_OBJECT} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_STATICLIB")
|
||||
endif()
|
||||
target_link_libraries(${LIB_STATIC} PRIVATE ${CURL_LIBS})
|
||||
# Remove the "lib" prefix since the library is already named "libcurl".
|
||||
@@ -137,7 +133,7 @@ if(BUILD_STATIC_LIBS)
|
||||
PREFIX "" OUTPUT_NAME "${LIBCURL_OUTPUT_NAME}"
|
||||
SUFFIX "${STATIC_LIB_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}"
|
||||
INTERFACE_COMPILE_DEFINITIONS "CURL_STATICLIB")
|
||||
if(HIDES_CURL_PRIVATE_SYMBOLS)
|
||||
if(CURL_HIDES_PRIVATE_SYMBOLS)
|
||||
set_property(TARGET ${LIB_STATIC} APPEND PROPERTY COMPILE_FLAGS "${CURL_CFLAG_SYMBOLS_HIDE}")
|
||||
set_property(TARGET ${LIB_STATIC} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS")
|
||||
endif()
|
||||
@@ -148,8 +144,8 @@ if(BUILD_STATIC_LIBS)
|
||||
endif()
|
||||
|
||||
target_include_directories(${LIB_STATIC} INTERFACE
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
$<BUILD_INTERFACE:${CURL_SOURCE_DIR}/include>)
|
||||
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
|
||||
"$<BUILD_INTERFACE:${CURL_SOURCE_DIR}/include>")
|
||||
endif()
|
||||
|
||||
if(BUILD_SHARED_LIBS)
|
||||
@@ -160,15 +156,15 @@ if(BUILD_SHARED_LIBS)
|
||||
if(CYGWIN)
|
||||
# For Cygwin always compile dllmain.c as a separate unit since it
|
||||
# includes windows.h, which should not be included in other units.
|
||||
set_source_files_properties(dllmain.c PROPERTIES
|
||||
set_source_files_properties("dllmain.c" PROPERTIES
|
||||
SKIP_UNITY_BUILD_INCLUSION ON)
|
||||
endif()
|
||||
set_property(TARGET ${LIB_SHARED} APPEND PROPERTY SOURCES dllmain.c)
|
||||
set_property(TARGET ${LIB_SHARED} APPEND PROPERTY SOURCES "dllmain.c")
|
||||
endif()
|
||||
if(WIN32)
|
||||
set_property(TARGET ${LIB_SHARED} APPEND PROPERTY SOURCES libcurl.rc)
|
||||
if(HIDES_CURL_PRIVATE_SYMBOLS)
|
||||
set_property(TARGET ${LIB_SHARED} APPEND PROPERTY SOURCES "${CURL_SOURCE_DIR}/libcurl.def")
|
||||
set_property(TARGET ${LIB_SHARED} APPEND PROPERTY SOURCES "libcurl.rc")
|
||||
if(CURL_HIDES_PRIVATE_SYMBOLS)
|
||||
set_property(TARGET ${LIB_SHARED} APPEND PROPERTY SOURCES "${CURL_SOURCE_DIR}/lib/libcurl.def")
|
||||
endif()
|
||||
endif()
|
||||
target_link_libraries(${LIB_SHARED} PRIVATE ${CURL_LIBS})
|
||||
@@ -177,7 +173,7 @@ if(BUILD_SHARED_LIBS)
|
||||
PREFIX "" OUTPUT_NAME "${LIBCURL_OUTPUT_NAME}"
|
||||
IMPORT_PREFIX "" IMPORT_SUFFIX "${IMPORT_LIB_SUFFIX}${CMAKE_IMPORT_LIBRARY_SUFFIX}"
|
||||
POSITION_INDEPENDENT_CODE ON)
|
||||
if(HIDES_CURL_PRIVATE_SYMBOLS)
|
||||
if(CURL_HIDES_PRIVATE_SYMBOLS)
|
||||
set_property(TARGET ${LIB_SHARED} APPEND PROPERTY COMPILE_FLAGS "${CURL_CFLAG_SYMBOLS_HIDE}")
|
||||
set_property(TARGET ${LIB_SHARED} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS")
|
||||
endif()
|
||||
@@ -188,8 +184,8 @@ if(BUILD_SHARED_LIBS)
|
||||
endif()
|
||||
|
||||
target_include_directories(${LIB_SHARED} INTERFACE
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
$<BUILD_INTERFACE:${CURL_SOURCE_DIR}/include>)
|
||||
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
|
||||
"$<BUILD_INTERFACE:${CURL_SOURCE_DIR}/include>")
|
||||
|
||||
if(CMAKE_DLL_NAME_WITH_SOVERSION OR
|
||||
CYGWIN OR
|
||||
@@ -203,22 +199,64 @@ if(BUILD_SHARED_LIBS)
|
||||
# up to v3.x and ELF from v3.x. I cannot imagine someone running CMake
|
||||
# on those ancient systems.
|
||||
CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
|
||||
set(soversion_default TRUE)
|
||||
set(_soversion_default TRUE)
|
||||
else()
|
||||
set(soversion_default FALSE)
|
||||
set(_soversion_default FALSE)
|
||||
endif()
|
||||
|
||||
option(CURL_LIBCURL_SOVERSION "Enable libcurl SOVERSION" ${soversion_default})
|
||||
option(CURL_LIBCURL_SOVERSION "Enable libcurl SOVERSION" ${_soversion_default})
|
||||
option(CURL_LIBCURL_VERSIONED_SYMBOLS "Enable libcurl versioned symbols" OFF)
|
||||
|
||||
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")
|
||||
include("${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake")
|
||||
|
||||
math(EXPR _cmakesoname "${VERSIONCHANGE} - ${VERSIONDEL}")
|
||||
set(_cmakeversion "${_cmakesoname}.${VERSIONDEL}.${VERSIONADD}")
|
||||
endif()
|
||||
|
||||
if(CURL_LIBCURL_SOVERSION)
|
||||
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}")
|
||||
set(CMAKEVERSION "${CMAKESONAME}.${VERSIONDEL}.${VERSIONADD}")
|
||||
|
||||
set_target_properties(${LIB_SHARED} PROPERTIES
|
||||
VERSION "${CMAKEVERSION}" SOVERSION "${CMAKESONAME}")
|
||||
VERSION "${_cmakeversion}" SOVERSION "${_cmakesoname}")
|
||||
endif()
|
||||
|
||||
## Versioned symbols
|
||||
|
||||
if(CURL_LIBCURL_VERSIONED_SYMBOLS)
|
||||
if(NOT DEFINED CURL_LIBCURL_VERSIONED_SYMBOLS_PREFIX)
|
||||
# Default to prefixes used by autotools
|
||||
if(CURL_WITH_MULTI_SSL)
|
||||
set(CURL_LIBCURL_VERSIONED_SYMBOLS_PREFIX "MULTISSL_")
|
||||
elseif(CURL_USE_OPENSSL)
|
||||
set(CURL_LIBCURL_VERSIONED_SYMBOLS_PREFIX "OPENSSL_")
|
||||
elseif(CURL_USE_MBEDTLS)
|
||||
set(CURL_LIBCURL_VERSIONED_SYMBOLS_PREFIX "MBEDTLS_")
|
||||
elseif(CURL_USE_BEARSSL)
|
||||
set(CURL_LIBCURL_VERSIONED_SYMBOLS_PREFIX "BEARSSL_")
|
||||
elseif(CURL_USE_WOLFSSL)
|
||||
set(CURL_LIBCURL_VERSIONED_SYMBOLS_PREFIX "WOLFSSL_")
|
||||
elseif(CURL_USE_GNUTLS)
|
||||
set(CURL_LIBCURL_VERSIONED_SYMBOLS_PREFIX "GNUTLS_")
|
||||
endif()
|
||||
endif()
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/libcurl.vers" "
|
||||
HIDDEN {};
|
||||
CURL_${CURL_LIBCURL_VERSIONED_SYMBOLS_PREFIX}${_cmakesoname}
|
||||
{
|
||||
global: curl_*;
|
||||
local: *;
|
||||
};")
|
||||
include(CheckCSourceCompiles)
|
||||
set(CMAKE_REQUIRED_LINK_OPTIONS "-Wl,--version-script=${CMAKE_CURRENT_BINARY_DIR}/libcurl.vers")
|
||||
check_c_source_compiles("int main(void) { return 0; }" HAVE_VERSIONED_SYMBOLS)
|
||||
if(HAVE_VERSIONED_SYMBOLS)
|
||||
# Superseded by LINK_OPTIONS in CMake 3.13 and later.
|
||||
set_target_properties(${LIB_SHARED} PROPERTIES LINK_FLAGS "${CMAKE_REQUIRED_LINK_OPTIONS}")
|
||||
else()
|
||||
message(WARNING "Versioned symbols requested, but not supported by the toolchain.")
|
||||
endif()
|
||||
unset(CMAKE_REQUIRED_LINK_OPTIONS)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -244,7 +282,7 @@ if(CURL_ENABLE_EXPORT_TARGET)
|
||||
endif()
|
||||
|
||||
export(TARGETS ${libcurl_export}
|
||||
FILE ${PROJECT_BINARY_DIR}/libcurl-target.cmake
|
||||
NAMESPACE ${PROJECT_NAME}::
|
||||
FILE "${PROJECT_BINARY_DIR}/libcurl-target.cmake"
|
||||
NAMESPACE ${PROJECT_NAME}::
|
||||
)
|
||||
endif()
|
||||
|
||||
+22
-22
@@ -337,13 +337,13 @@ CURLcode Curl_altsvc_ctrl(struct altsvcinfo *asi, const long ctrl)
|
||||
*/
|
||||
void Curl_altsvc_cleanup(struct altsvcinfo **altsvcp)
|
||||
{
|
||||
struct Curl_llist_element *e;
|
||||
struct Curl_llist_element *n;
|
||||
if(*altsvcp) {
|
||||
struct Curl_llist_node *e;
|
||||
struct Curl_llist_node *n;
|
||||
struct altsvcinfo *altsvc = *altsvcp;
|
||||
for(e = altsvc->list.head; e; e = n) {
|
||||
struct altsvc *as = e->ptr;
|
||||
n = e->next;
|
||||
for(e = Curl_llist_head(&altsvc->list); e; e = n) {
|
||||
struct altsvc *as = Curl_node_elem(e);
|
||||
n = Curl_node_next(e);
|
||||
altsvc_free(as);
|
||||
}
|
||||
free(altsvc->filename);
|
||||
@@ -358,8 +358,6 @@ void Curl_altsvc_cleanup(struct altsvcinfo **altsvcp)
|
||||
CURLcode Curl_altsvc_save(struct Curl_easy *data,
|
||||
struct altsvcinfo *altsvc, const char *file)
|
||||
{
|
||||
struct Curl_llist_element *e;
|
||||
struct Curl_llist_element *n;
|
||||
CURLcode result = CURLE_OK;
|
||||
FILE *out;
|
||||
char *tempstore = NULL;
|
||||
@@ -378,12 +376,14 @@ CURLcode Curl_altsvc_save(struct Curl_easy *data,
|
||||
|
||||
result = Curl_fopen(data, file, &out, &tempstore);
|
||||
if(!result) {
|
||||
struct Curl_llist_node *e;
|
||||
struct Curl_llist_node *n;
|
||||
fputs("# Your alt-svc cache. https://curl.se/docs/alt-svc.html\n"
|
||||
"# This file was generated by libcurl! Edit at your own risk.\n",
|
||||
out);
|
||||
for(e = altsvc->list.head; e; e = n) {
|
||||
struct altsvc *as = e->ptr;
|
||||
n = e->next;
|
||||
for(e = Curl_llist_head(&altsvc->list); e; e = n) {
|
||||
struct altsvc *as = Curl_node_elem(e);
|
||||
n = Curl_node_next(e);
|
||||
result = altsvc_out(as, out);
|
||||
if(result)
|
||||
break;
|
||||
@@ -440,15 +440,15 @@ static bool hostcompare(const char *host, const char *check)
|
||||
static void altsvc_flush(struct altsvcinfo *asi, enum alpnid srcalpnid,
|
||||
const char *srchost, unsigned short srcport)
|
||||
{
|
||||
struct Curl_llist_element *e;
|
||||
struct Curl_llist_element *n;
|
||||
for(e = asi->list.head; e; e = n) {
|
||||
struct altsvc *as = e->ptr;
|
||||
n = e->next;
|
||||
struct Curl_llist_node *e;
|
||||
struct Curl_llist_node *n;
|
||||
for(e = Curl_llist_head(&asi->list); e; e = n) {
|
||||
struct altsvc *as = Curl_node_elem(e);
|
||||
n = Curl_node_next(e);
|
||||
if((srcalpnid == as->src.alpnid) &&
|
||||
(srcport == as->src.port) &&
|
||||
hostcompare(srchost, as->src.host)) {
|
||||
Curl_llist_remove(&asi->list, e, NULL);
|
||||
Curl_node_remove(e);
|
||||
altsvc_free(as);
|
||||
}
|
||||
}
|
||||
@@ -677,19 +677,19 @@ bool Curl_altsvc_lookup(struct altsvcinfo *asi,
|
||||
struct altsvc **dstentry,
|
||||
const int versions) /* one or more bits */
|
||||
{
|
||||
struct Curl_llist_element *e;
|
||||
struct Curl_llist_element *n;
|
||||
struct Curl_llist_node *e;
|
||||
struct Curl_llist_node *n;
|
||||
time_t now = time(NULL);
|
||||
DEBUGASSERT(asi);
|
||||
DEBUGASSERT(srchost);
|
||||
DEBUGASSERT(dstentry);
|
||||
|
||||
for(e = asi->list.head; e; e = n) {
|
||||
struct altsvc *as = e->ptr;
|
||||
n = e->next;
|
||||
for(e = Curl_llist_head(&asi->list); e; e = n) {
|
||||
struct altsvc *as = Curl_node_elem(e);
|
||||
n = Curl_node_next(e);
|
||||
if(as->expires < now) {
|
||||
/* an expired entry, remove */
|
||||
Curl_llist_remove(&asi->list, e, NULL);
|
||||
Curl_node_remove(e);
|
||||
altsvc_free(as);
|
||||
continue;
|
||||
}
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ struct altsvc {
|
||||
time_t expires;
|
||||
bool persist;
|
||||
unsigned int prio;
|
||||
struct Curl_llist_element node;
|
||||
struct Curl_llist_node node;
|
||||
};
|
||||
|
||||
struct altsvcinfo {
|
||||
|
||||
+1
-251
@@ -54,7 +54,6 @@
|
||||
# define RESOLVER_ENOMEM ENOMEM
|
||||
#endif
|
||||
|
||||
#include "system_win32.h"
|
||||
#include "urldata.h"
|
||||
#include "sendf.h"
|
||||
#include "hostip.h"
|
||||
@@ -145,22 +144,9 @@ static bool init_resolve_thread(struct Curl_easy *data,
|
||||
const char *hostname, int port,
|
||||
const struct addrinfo *hints);
|
||||
|
||||
#ifdef _WIN32
|
||||
/* Thread sync data used by GetAddrInfoExW for win8+ */
|
||||
struct thread_sync_data_w8
|
||||
{
|
||||
OVERLAPPED overlapped;
|
||||
ADDRINFOEXW_ *res;
|
||||
HANDLE cancel_ev;
|
||||
ADDRINFOEXW_ hints;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Data for synchronization between resolver thread and its parent */
|
||||
struct thread_sync_data {
|
||||
#ifdef _WIN32
|
||||
struct thread_sync_data_w8 w8;
|
||||
#endif
|
||||
curl_mutex_t *mtx;
|
||||
int done;
|
||||
int port;
|
||||
@@ -179,9 +165,6 @@ struct thread_sync_data {
|
||||
};
|
||||
|
||||
struct thread_data {
|
||||
#ifdef _WIN32
|
||||
HANDLE complete_ev;
|
||||
#endif
|
||||
curl_thread_t thread_hnd;
|
||||
unsigned int poll_interval;
|
||||
timediff_t interval_end;
|
||||
@@ -293,162 +276,6 @@ static CURLcode getaddrinfo_complete(struct Curl_easy *data)
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
static VOID WINAPI
|
||||
query_complete(DWORD err, DWORD bytes, LPWSAOVERLAPPED overlapped)
|
||||
{
|
||||
size_t ss_size;
|
||||
const ADDRINFOEXW_ *ai;
|
||||
struct Curl_addrinfo *ca;
|
||||
struct Curl_addrinfo *cafirst = NULL;
|
||||
struct Curl_addrinfo *calast = NULL;
|
||||
#ifndef CURL_DISABLE_SOCKETPAIR
|
||||
#ifdef USE_EVENTFD
|
||||
const void *buf;
|
||||
const uint64_t val = 1;
|
||||
#else
|
||||
char buf[1];
|
||||
#endif
|
||||
#endif
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wcast-align"
|
||||
#endif
|
||||
struct thread_sync_data *tsd =
|
||||
CONTAINING_RECORD(overlapped, struct thread_sync_data, w8.overlapped);
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
struct thread_data *td = tsd->td;
|
||||
const ADDRINFOEXW_ *res = tsd->w8.res;
|
||||
int error = (int)err;
|
||||
(void)bytes;
|
||||
|
||||
if(error == ERROR_SUCCESS) {
|
||||
/* traverse the addrinfo list */
|
||||
|
||||
for(ai = res; ai != NULL; ai = ai->ai_next) {
|
||||
size_t namelen = ai->ai_canonname ? wcslen(ai->ai_canonname) + 1 : 0;
|
||||
/* ignore elements with unsupported address family, */
|
||||
/* settle family-specific sockaddr structure size. */
|
||||
if(ai->ai_family == AF_INET)
|
||||
ss_size = sizeof(struct sockaddr_in);
|
||||
#ifdef USE_IPV6
|
||||
else if(ai->ai_family == AF_INET6)
|
||||
ss_size = sizeof(struct sockaddr_in6);
|
||||
#endif
|
||||
else
|
||||
continue;
|
||||
|
||||
/* ignore elements without required address info */
|
||||
if(!ai->ai_addr || !(ai->ai_addrlen > 0))
|
||||
continue;
|
||||
|
||||
/* ignore elements with bogus address size */
|
||||
if((size_t)ai->ai_addrlen < ss_size)
|
||||
continue;
|
||||
|
||||
ca = malloc(sizeof(struct Curl_addrinfo) + ss_size + namelen);
|
||||
if(!ca) {
|
||||
error = EAI_MEMORY;
|
||||
break;
|
||||
}
|
||||
|
||||
/* copy each structure member individually, member ordering, */
|
||||
/* size, or padding might be different for each platform. */
|
||||
ca->ai_flags = ai->ai_flags;
|
||||
ca->ai_family = ai->ai_family;
|
||||
ca->ai_socktype = ai->ai_socktype;
|
||||
ca->ai_protocol = ai->ai_protocol;
|
||||
ca->ai_addrlen = (curl_socklen_t)ss_size;
|
||||
ca->ai_addr = NULL;
|
||||
ca->ai_canonname = NULL;
|
||||
ca->ai_next = NULL;
|
||||
|
||||
ca->ai_addr = (void *)((char *)ca + sizeof(struct Curl_addrinfo));
|
||||
memcpy(ca->ai_addr, ai->ai_addr, ss_size);
|
||||
|
||||
if(namelen) {
|
||||
size_t i;
|
||||
ca->ai_canonname = (void *)((char *)ca->ai_addr + ss_size);
|
||||
for(i = 0; i < namelen; ++i) /* convert wide string to ascii */
|
||||
ca->ai_canonname[i] = (char)ai->ai_canonname[i];
|
||||
ca->ai_canonname[namelen] = '\0';
|
||||
}
|
||||
|
||||
/* if the return list is empty, this becomes the first element */
|
||||
if(!cafirst)
|
||||
cafirst = ca;
|
||||
|
||||
/* add this element last in the return list */
|
||||
if(calast)
|
||||
calast->ai_next = ca;
|
||||
calast = ca;
|
||||
}
|
||||
|
||||
/* if we failed, also destroy the Curl_addrinfo list */
|
||||
if(error) {
|
||||
Curl_freeaddrinfo(cafirst);
|
||||
cafirst = NULL;
|
||||
}
|
||||
else if(!cafirst) {
|
||||
#ifdef EAI_NONAME
|
||||
/* rfc3493 conformant */
|
||||
error = EAI_NONAME;
|
||||
#else
|
||||
/* rfc3493 obsoleted */
|
||||
error = EAI_NODATA;
|
||||
#endif
|
||||
#ifdef USE_WINSOCK
|
||||
SET_SOCKERRNO(error);
|
||||
#endif
|
||||
}
|
||||
tsd->res = cafirst;
|
||||
}
|
||||
|
||||
if(tsd->w8.res) {
|
||||
Curl_FreeAddrInfoExW(tsd->w8.res);
|
||||
tsd->w8.res = NULL;
|
||||
}
|
||||
|
||||
if(error) {
|
||||
tsd->sock_error = SOCKERRNO?SOCKERRNO:error;
|
||||
if(tsd->sock_error == 0)
|
||||
tsd->sock_error = RESOLVER_ENOMEM;
|
||||
}
|
||||
else {
|
||||
Curl_addrinfo_set_port(tsd->res, tsd->port);
|
||||
}
|
||||
|
||||
Curl_mutex_acquire(tsd->mtx);
|
||||
if(tsd->done) {
|
||||
/* too late, gotta clean up the mess */
|
||||
Curl_mutex_release(tsd->mtx);
|
||||
destroy_thread_sync_data(tsd);
|
||||
free(td);
|
||||
}
|
||||
else {
|
||||
#ifndef CURL_DISABLE_SOCKETPAIR
|
||||
if(tsd->sock_pair[1] != CURL_SOCKET_BAD) {
|
||||
#ifdef USE_EVENTFD
|
||||
buf = &val;
|
||||
#else
|
||||
buf[0] = 1;
|
||||
#endif
|
||||
/* DNS has been resolved, signal client task */
|
||||
if(wakeup_write(tsd->sock_pair[1], buf, sizeof(buf)) < 0) {
|
||||
/* update sock_erro to errno */
|
||||
tsd->sock_error = SOCKERRNO;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
tsd->done = 1;
|
||||
Curl_mutex_release(tsd->mtx);
|
||||
if(td->complete_ev)
|
||||
SetEvent(td->complete_ev); /* Notify caller that the query completed */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GETADDRINFO
|
||||
|
||||
@@ -585,26 +412,9 @@ static void destroy_async_data(struct Curl_async *async)
|
||||
Curl_mutex_release(td->tsd.mtx);
|
||||
|
||||
if(!done) {
|
||||
#ifdef _WIN32
|
||||
if(td->complete_ev) {
|
||||
CloseHandle(td->complete_ev);
|
||||
td->complete_ev = NULL;
|
||||
}
|
||||
#endif
|
||||
if(td->thread_hnd != curl_thread_t_null) {
|
||||
Curl_thread_destroy(td->thread_hnd);
|
||||
td->thread_hnd = curl_thread_t_null;
|
||||
}
|
||||
Curl_thread_destroy(td->thread_hnd);
|
||||
}
|
||||
else {
|
||||
#ifdef _WIN32
|
||||
if(td->complete_ev) {
|
||||
Curl_GetAddrInfoExCancel(&td->tsd.w8.cancel_ev);
|
||||
WaitForSingleObject(td->complete_ev, INFINITE);
|
||||
CloseHandle(td->complete_ev);
|
||||
td->complete_ev = NULL;
|
||||
}
|
||||
#endif
|
||||
if(td->thread_hnd != curl_thread_t_null)
|
||||
Curl_thread_join(&td->thread_hnd);
|
||||
|
||||
@@ -650,9 +460,6 @@ static bool init_resolve_thread(struct Curl_easy *data,
|
||||
asp->status = 0;
|
||||
asp->dns = NULL;
|
||||
td->thread_hnd = curl_thread_t_null;
|
||||
#ifdef _WIN32
|
||||
td->complete_ev = NULL;
|
||||
#endif
|
||||
|
||||
if(!init_thread_sync_data(td, hostname, port, hints)) {
|
||||
asp->tdata = NULL;
|
||||
@@ -668,42 +475,6 @@ static bool init_resolve_thread(struct Curl_easy *data,
|
||||
/* The thread will set this to 1 when complete. */
|
||||
td->tsd.done = 0;
|
||||
|
||||
#ifdef _WIN32
|
||||
if(Curl_isWindows8OrGreater && Curl_FreeAddrInfoExW &&
|
||||
Curl_GetAddrInfoExCancel && Curl_GetAddrInfoExW &&
|
||||
!Curl_win32_impersonating()) {
|
||||
#define MAX_NAME_LEN 256 /* max domain name is 253 chars */
|
||||
#define MAX_PORT_LEN 8
|
||||
WCHAR namebuf[MAX_NAME_LEN];
|
||||
WCHAR portbuf[MAX_PORT_LEN];
|
||||
/* calculate required length */
|
||||
int w_len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, hostname,
|
||||
-1, NULL, 0);
|
||||
if((w_len > 0) && (w_len < MAX_NAME_LEN)) {
|
||||
/* do utf8 conversion */
|
||||
w_len = MultiByteToWideChar(CP_UTF8, 0, hostname, -1, namebuf, w_len);
|
||||
if((w_len > 0) && (w_len < MAX_NAME_LEN)) {
|
||||
swprintf(portbuf, MAX_PORT_LEN, L"%d", port);
|
||||
td->tsd.w8.hints.ai_family = hints->ai_family;
|
||||
td->tsd.w8.hints.ai_socktype = hints->ai_socktype;
|
||||
td->complete_ev = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
if(!td->complete_ev) {
|
||||
/* failed to start, mark it as done here for proper cleanup. */
|
||||
td->tsd.done = 1;
|
||||
goto err_exit;
|
||||
}
|
||||
err = Curl_GetAddrInfoExW(namebuf, portbuf, NS_DNS,
|
||||
NULL, &td->tsd.w8.hints, &td->tsd.w8.res,
|
||||
NULL, &td->tsd.w8.overlapped,
|
||||
&query_complete, &td->tsd.w8.cancel_ev);
|
||||
if(err != WSA_IO_PENDING)
|
||||
query_complete((DWORD)err, 0, &td->tsd.w8.overlapped);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GETADDRINFO
|
||||
td->thread_hnd = Curl_thread_create(getaddrinfo_thread, &td->tsd);
|
||||
#else
|
||||
@@ -740,23 +511,9 @@ static CURLcode thread_wait_resolv(struct Curl_easy *data,
|
||||
DEBUGASSERT(data);
|
||||
td = data->state.async.tdata;
|
||||
DEBUGASSERT(td);
|
||||
#ifdef _WIN32
|
||||
DEBUGASSERT(td->complete_ev || td->thread_hnd != curl_thread_t_null);
|
||||
#else
|
||||
DEBUGASSERT(td->thread_hnd != curl_thread_t_null);
|
||||
#endif
|
||||
|
||||
/* wait for the thread to resolve the name */
|
||||
#ifdef _WIN32
|
||||
if(td->complete_ev) {
|
||||
WaitForSingleObject(td->complete_ev, INFINITE);
|
||||
CloseHandle(td->complete_ev);
|
||||
td->complete_ev = NULL;
|
||||
if(entry)
|
||||
result = getaddrinfo_complete(data);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if(Curl_thread_join(&td->thread_hnd)) {
|
||||
if(entry)
|
||||
result = getaddrinfo_complete(data);
|
||||
@@ -793,13 +550,6 @@ void Curl_resolver_kill(struct Curl_easy *data)
|
||||
/* If we are still resolving, we must wait for the threads to fully clean up,
|
||||
unfortunately. Otherwise, we can simply cancel to clean up any resolver
|
||||
data. */
|
||||
#ifdef _WIN32
|
||||
if(td && td->complete_ev) {
|
||||
Curl_GetAddrInfoExCancel(&td->tsd.w8.cancel_ev);
|
||||
(void)thread_wait_resolv(data, NULL, FALSE);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if(td && td->thread_hnd != curl_thread_t_null
|
||||
&& (data->set.quick_exit != 1L))
|
||||
(void)thread_wait_resolv(data, NULL, FALSE);
|
||||
|
||||
+69
@@ -91,6 +91,23 @@ static size_t chunk_read(struct buf_chunk *chunk,
|
||||
}
|
||||
}
|
||||
|
||||
static size_t chunk_unwrite(struct buf_chunk *chunk, size_t len)
|
||||
{
|
||||
size_t n = chunk->w_offset - chunk->r_offset;
|
||||
DEBUGASSERT(chunk->w_offset >= chunk->r_offset);
|
||||
if(!n) {
|
||||
return 0;
|
||||
}
|
||||
else if(n <= len) {
|
||||
chunk->r_offset = chunk->w_offset = 0;
|
||||
return n;
|
||||
}
|
||||
else {
|
||||
chunk->w_offset -= len;
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t chunk_slurpn(struct buf_chunk *chunk, size_t max_len,
|
||||
Curl_bufq_reader *reader,
|
||||
void *reader_ctx, CURLcode *err)
|
||||
@@ -363,6 +380,49 @@ static void prune_head(struct bufq *q)
|
||||
}
|
||||
}
|
||||
|
||||
static struct buf_chunk *chunk_prev(struct buf_chunk *head,
|
||||
struct buf_chunk *chunk)
|
||||
{
|
||||
while(head) {
|
||||
if(head == chunk)
|
||||
return NULL;
|
||||
if(head->next == chunk)
|
||||
return head;
|
||||
head = head->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void prune_tail(struct bufq *q)
|
||||
{
|
||||
struct buf_chunk *chunk;
|
||||
|
||||
while(q->tail && chunk_is_empty(q->tail)) {
|
||||
chunk = q->tail;
|
||||
q->tail = chunk_prev(q->head, chunk);
|
||||
if(q->tail)
|
||||
q->tail->next = NULL;
|
||||
if(q->head == chunk)
|
||||
q->head = q->tail;
|
||||
if(q->pool) {
|
||||
bufcp_put(q->pool, chunk);
|
||||
--q->chunk_count;
|
||||
}
|
||||
else if((q->chunk_count > q->max_chunks) ||
|
||||
(q->opts & BUFQ_OPT_NO_SPARES)) {
|
||||
/* SOFT_LIMIT allowed us more than max. free spares until
|
||||
* we are at max again. Or free them if we are configured
|
||||
* to not use spares. */
|
||||
free(chunk);
|
||||
--q->chunk_count;
|
||||
}
|
||||
else {
|
||||
chunk->next = q->spare;
|
||||
q->spare = chunk;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static struct buf_chunk *get_non_full_tail(struct bufq *q)
|
||||
{
|
||||
struct buf_chunk *chunk;
|
||||
@@ -428,6 +488,15 @@ CURLcode Curl_bufq_cwrite(struct bufq *q,
|
||||
return result;
|
||||
}
|
||||
|
||||
CURLcode Curl_bufq_unwrite(struct bufq *q, size_t len)
|
||||
{
|
||||
while(len && q->tail) {
|
||||
len -= chunk_unwrite(q->head, len);
|
||||
prune_tail(q);
|
||||
}
|
||||
return len? CURLE_AGAIN : CURLE_OK;
|
||||
}
|
||||
|
||||
ssize_t Curl_bufq_read(struct bufq *q, unsigned char *buf, size_t len,
|
||||
CURLcode *err)
|
||||
{
|
||||
|
||||
@@ -182,6 +182,12 @@ CURLcode Curl_bufq_cwrite(struct bufq *q,
|
||||
const char *buf, size_t len,
|
||||
size_t *pnwritten);
|
||||
|
||||
/**
|
||||
* Remove `len` bytes from the end of the buffer queue again.
|
||||
* Returns CURLE_AGAIN if less than `len` bytes were in the queue.
|
||||
*/
|
||||
CURLcode Curl_bufq_unwrite(struct bufq *q, size_t len);
|
||||
|
||||
/**
|
||||
* Read buf from the start of the buffer queue. The buf is copied
|
||||
* and the amount of copied bytes is returned.
|
||||
|
||||
+172
-147
@@ -119,7 +119,7 @@ size_t Curl_hyper_send(void *userp, hyper_context *ctx,
|
||||
|
||||
DEBUGF(infof(data, "Curl_hyper_send(%zu)", buflen));
|
||||
result = Curl_conn_send(data, io_ctx->sockindex,
|
||||
(void *)buf, buflen, &nwrote);
|
||||
(void *)buf, buflen, FALSE, &nwrote);
|
||||
if(result == CURLE_AGAIN) {
|
||||
DEBUGF(infof(data, "Curl_hyper_send(%zu) -> EAGAIN", buflen));
|
||||
/* would block, register interest */
|
||||
@@ -352,6 +352,8 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
|
||||
(void)conn;
|
||||
|
||||
if(data->hyp.send_body_waker) {
|
||||
/* If there is still something to upload, wake it to give it
|
||||
* another try. */
|
||||
hyper_waker_wake(data->hyp.send_body_waker);
|
||||
data->hyp.send_body_waker = NULL;
|
||||
}
|
||||
@@ -367,7 +369,7 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
|
||||
h->write_waker = NULL;
|
||||
}
|
||||
|
||||
do {
|
||||
while(1) {
|
||||
hyper_task_return_type t;
|
||||
task = hyper_executor_poll(h->exec);
|
||||
if(!task) {
|
||||
@@ -391,22 +393,22 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
|
||||
switch(code) {
|
||||
case HYPERE_ABORTED_BY_CALLBACK:
|
||||
result = CURLE_OK;
|
||||
break;
|
||||
goto out;
|
||||
case HYPERE_UNEXPECTED_EOF:
|
||||
if(!data->req.bytecount)
|
||||
result = CURLE_GOT_NOTHING;
|
||||
else
|
||||
result = CURLE_RECV_ERROR;
|
||||
break;
|
||||
goto out;
|
||||
case HYPERE_INVALID_PEER_MESSAGE:
|
||||
/* bump headerbytecount to avoid the count remaining at zero and
|
||||
appearing to not having read anything from the peer at all */
|
||||
data->req.headerbytecount++;
|
||||
result = CURLE_UNSUPPORTED_PROTOCOL; /* maybe */
|
||||
break;
|
||||
goto out;
|
||||
default:
|
||||
result = CURLE_RECV_ERROR;
|
||||
break;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
data->req.done = TRUE;
|
||||
@@ -416,7 +418,7 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
|
||||
else if(t == HYPER_TASK_EMPTY) {
|
||||
void *userdata = hyper_task_userdata(task);
|
||||
hyper_task_free(task);
|
||||
if((userdata_t)userdata == USERDATA_RESP_BODY) {
|
||||
if(userdata == (void *)USERDATA_RESP_BODY) {
|
||||
/* end of transfer */
|
||||
data->req.done = TRUE;
|
||||
infof(data, "hyperstream is done");
|
||||
@@ -428,103 +430,115 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
|
||||
}
|
||||
else {
|
||||
/* A background task for hyper; ignore */
|
||||
DEBUGF(infof(data, "hyper: some background task done"));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if(t == HYPER_TASK_RESPONSE) {
|
||||
resp = hyper_task_value(task);
|
||||
hyper_task_free(task);
|
||||
|
||||
DEBUGASSERT(HYPER_TASK_RESPONSE);
|
||||
*didwhat = KEEP_RECV;
|
||||
if(!resp) {
|
||||
failf(data, "hyperstream: could not get response");
|
||||
result = CURLE_RECV_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
resp = hyper_task_value(task);
|
||||
hyper_task_free(task);
|
||||
http_status = hyper_response_status(resp);
|
||||
http_version = hyper_response_version(resp);
|
||||
reasonp = hyper_response_reason_phrase(resp);
|
||||
reason_len = hyper_response_reason_phrase_len(resp);
|
||||
|
||||
*didwhat = KEEP_RECV;
|
||||
if(!resp) {
|
||||
failf(data, "hyperstream: could not get response");
|
||||
return CURLE_RECV_ERROR;
|
||||
}
|
||||
if(http_status == 417 && Curl_http_exp100_is_selected(data)) {
|
||||
infof(data, "Got 417 while waiting for a 100");
|
||||
data->state.disableexpect = TRUE;
|
||||
data->req.newurl = strdup(data->state.url);
|
||||
Curl_req_abort_sending(data);
|
||||
}
|
||||
|
||||
http_status = hyper_response_status(resp);
|
||||
http_version = hyper_response_version(resp);
|
||||
reasonp = hyper_response_reason_phrase(resp);
|
||||
reason_len = hyper_response_reason_phrase_len(resp);
|
||||
result = status_line(data, conn,
|
||||
http_status, http_version, reasonp, reason_len);
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
if(http_status == 417 && Curl_http_exp100_is_selected(data)) {
|
||||
infof(data, "Got 417 while waiting for a 100");
|
||||
data->state.disableexpect = TRUE;
|
||||
data->req.newurl = strdup(data->state.url);
|
||||
Curl_req_abort_sending(data);
|
||||
}
|
||||
headers = hyper_response_headers(resp);
|
||||
if(!headers) {
|
||||
failf(data, "hyperstream: could not get response headers");
|
||||
result = CURLE_RECV_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = status_line(data, conn,
|
||||
http_status, http_version, reasonp, reason_len);
|
||||
if(result)
|
||||
break;
|
||||
/* the headers are already received */
|
||||
hyper_headers_foreach(headers, hyper_each_header, data);
|
||||
if(data->state.hresult) {
|
||||
result = data->state.hresult;
|
||||
goto out;
|
||||
}
|
||||
|
||||
headers = hyper_response_headers(resp);
|
||||
if(!headers) {
|
||||
failf(data, "hyperstream: could not get response headers");
|
||||
result = CURLE_RECV_ERROR;
|
||||
break;
|
||||
}
|
||||
result = empty_header(data);
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
/* the headers are already received */
|
||||
hyper_headers_foreach(headers, hyper_each_header, data);
|
||||
if(data->state.hresult) {
|
||||
result = data->state.hresult;
|
||||
break;
|
||||
}
|
||||
|
||||
result = empty_header(data);
|
||||
if(result)
|
||||
break;
|
||||
|
||||
k->deductheadercount =
|
||||
(100 <= http_status && 199 >= http_status)?k->headerbytecount:0;
|
||||
k->deductheadercount =
|
||||
(100 <= http_status && 199 >= http_status)?k->headerbytecount:0;
|
||||
#ifdef USE_WEBSOCKETS
|
||||
if(k->upgr101 == UPGR101_WS) {
|
||||
if(http_status == 101) {
|
||||
/* verify the response */
|
||||
result = Curl_ws_accept(data, NULL, 0);
|
||||
if(result)
|
||||
return result;
|
||||
if(k->upgr101 == UPGR101_WS) {
|
||||
if(http_status == 101) {
|
||||
/* verify the response */
|
||||
result = Curl_ws_accept(data, NULL, 0);
|
||||
if(result)
|
||||
goto out;
|
||||
}
|
||||
else {
|
||||
failf(data, "Expected 101, got %u", k->httpcode);
|
||||
result = CURLE_HTTP_RETURNED_ERROR;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
else {
|
||||
failf(data, "Expected 101, got %u", k->httpcode);
|
||||
result = CURLE_HTTP_RETURNED_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Curl_http_auth_act() checks what authentication methods that are
|
||||
* available and decides which one (if any) to use. It will set 'newurl'
|
||||
* if an auth method was picked. */
|
||||
result = Curl_http_auth_act(data);
|
||||
if(result)
|
||||
break;
|
||||
/* Curl_http_auth_act() checks what authentication methods that are
|
||||
* available and decides which one (if any) to use. It will set 'newurl'
|
||||
* if an auth method was picked. */
|
||||
result = Curl_http_auth_act(data);
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
resp_body = hyper_response_body(resp);
|
||||
if(!resp_body) {
|
||||
failf(data, "hyperstream: could not get response body");
|
||||
result = CURLE_RECV_ERROR;
|
||||
break;
|
||||
}
|
||||
foreach = hyper_body_foreach(resp_body, hyper_body_chunk, data);
|
||||
if(!foreach) {
|
||||
failf(data, "hyperstream: body foreach failed");
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
break;
|
||||
}
|
||||
hyper_task_set_userdata(foreach, (void *)USERDATA_RESP_BODY);
|
||||
if(HYPERE_OK != hyper_executor_push(h->exec, foreach)) {
|
||||
failf(data, "Couldn't hyper_executor_push the body-foreach");
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
break;
|
||||
}
|
||||
resp_body = hyper_response_body(resp);
|
||||
if(!resp_body) {
|
||||
failf(data, "hyperstream: could not get response body");
|
||||
result = CURLE_RECV_ERROR;
|
||||
goto out;
|
||||
}
|
||||
foreach = hyper_body_foreach(resp_body, hyper_body_chunk, data);
|
||||
if(!foreach) {
|
||||
failf(data, "hyperstream: body foreach failed");
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
hyper_task_set_userdata(foreach, (void *)USERDATA_RESP_BODY);
|
||||
if(HYPERE_OK != hyper_executor_push(h->exec, foreach)) {
|
||||
failf(data, "Couldn't hyper_executor_push the body-foreach");
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
hyper_response_free(resp);
|
||||
resp = NULL;
|
||||
} while(1);
|
||||
hyper_response_free(resp);
|
||||
resp = NULL;
|
||||
}
|
||||
else {
|
||||
DEBUGF(infof(data, "hyper: unhandled tasktype %x", t));
|
||||
}
|
||||
} /* while(1) */
|
||||
|
||||
if(!result && Curl_xfer_needs_flush(data)) {
|
||||
DEBUGF(infof(data, "Curl_hyper_stream(), connection needs flush"));
|
||||
result = Curl_xfer_flush(data);
|
||||
}
|
||||
|
||||
out:
|
||||
DEBUGF(infof(data, "Curl_hyper_stream() -> %d", result));
|
||||
if(resp)
|
||||
hyper_response_free(resp);
|
||||
return result;
|
||||
@@ -671,10 +685,13 @@ static int uploadstreamed(void *userdata, hyper_context *ctx,
|
||||
/* increasing the writebytecount here is a little premature but we
|
||||
do not know exactly when the body is sent */
|
||||
data->req.writebytecount += fillcount;
|
||||
if(eos)
|
||||
data->req.eos_read = TRUE;
|
||||
Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
|
||||
rc = HYPER_POLL_READY;
|
||||
}
|
||||
else if(eos) {
|
||||
data->req.eos_read = TRUE;
|
||||
*chunk = NULL;
|
||||
rc = HYPER_POLL_READY;
|
||||
}
|
||||
@@ -686,9 +703,15 @@ static int uploadstreamed(void *userdata, hyper_context *ctx,
|
||||
rc = HYPER_POLL_PENDING;
|
||||
}
|
||||
|
||||
if(!data->req.upload_done && data->req.eos_read) {
|
||||
DEBUGF(infof(data, "hyper: uploadstreamed(), upload is done"));
|
||||
result = Curl_req_set_upload_done(data);
|
||||
}
|
||||
|
||||
out:
|
||||
Curl_multi_xfer_ulbuf_release(data, xfer_ulbuf);
|
||||
data->state.hresult = result;
|
||||
DEBUGF(infof(data, "hyper: uploadstreamed() -> %d", result));
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -702,8 +725,9 @@ static CURLcode finalize_request(struct Curl_easy *data,
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct dynbuf req;
|
||||
if((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD))
|
||||
if((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) {
|
||||
Curl_pgrsSetUploadSize(data, 0); /* no request body */
|
||||
}
|
||||
else {
|
||||
hyper_body *body;
|
||||
Curl_dyn_init(&req, DYN_HTTP_REQUEST);
|
||||
@@ -821,21 +845,21 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
|
||||
*done = TRUE;
|
||||
result = Curl_client_start(data);
|
||||
if(result)
|
||||
return result;
|
||||
goto out;
|
||||
|
||||
/* Add collecting of headers written to client. For a new connection,
|
||||
* we might have done that already, but reuse
|
||||
* or multiplex needs it here as well. */
|
||||
result = Curl_headers_init(data);
|
||||
if(result)
|
||||
return result;
|
||||
goto out;
|
||||
|
||||
infof(data, "Time for the Hyper dance");
|
||||
memset(h, 0, sizeof(struct hyptransfer));
|
||||
|
||||
result = Curl_http_host(data, conn);
|
||||
if(result)
|
||||
return result;
|
||||
goto out;
|
||||
|
||||
Curl_http_method(data, conn, &method, &httpreq);
|
||||
|
||||
@@ -846,33 +870,35 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
|
||||
char *pq = NULL;
|
||||
if(data->state.up.query) {
|
||||
pq = aprintf("%s?%s", data->state.up.path, data->state.up.query);
|
||||
if(!pq)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
if(!pq) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
result = Curl_http_output_auth(data, conn, method, httpreq,
|
||||
(pq ? pq : data->state.up.path), FALSE);
|
||||
free(pq);
|
||||
if(result)
|
||||
return result;
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = Curl_http_req_set_reader(data, httpreq, &te);
|
||||
if(result)
|
||||
goto error;
|
||||
goto out;
|
||||
|
||||
result = Curl_http_range(data, httpreq);
|
||||
if(result)
|
||||
return result;
|
||||
goto out;
|
||||
|
||||
result = Curl_http_useragent(data);
|
||||
if(result)
|
||||
return result;
|
||||
goto out;
|
||||
|
||||
io = hyper_io_new();
|
||||
if(!io) {
|
||||
failf(data, "Couldn't create hyper IO");
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
/* tell Hyper how to read/write network data */
|
||||
h->io_ctx.data = data;
|
||||
@@ -887,7 +913,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
|
||||
if(!h->exec) {
|
||||
failf(data, "Couldn't create hyper executor");
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -895,12 +921,12 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
|
||||
if(!options) {
|
||||
failf(data, "Couldn't create hyper client options");
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
if(conn->alpn == CURL_HTTP_VERSION_2) {
|
||||
failf(data, "ALPN protocol h2 not supported with Hyper");
|
||||
result = CURLE_UNSUPPORTED_PROTOCOL;
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
hyper_clientconn_options_set_preserve_header_case(options, 1);
|
||||
hyper_clientconn_options_set_preserve_header_order(options, 1);
|
||||
@@ -913,7 +939,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
|
||||
if(!handshake) {
|
||||
failf(data, "Couldn't create hyper client handshake");
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
io = NULL;
|
||||
options = NULL;
|
||||
@@ -921,7 +947,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
|
||||
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;
|
||||
goto out;
|
||||
}
|
||||
handshake = NULL; /* ownership passed on */
|
||||
|
||||
@@ -929,7 +955,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
|
||||
if(!task) {
|
||||
failf(data, "Couldn't hyper_executor_poll the handshake");
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
|
||||
client = hyper_task_value(task);
|
||||
@@ -939,7 +965,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
|
||||
if(!req) {
|
||||
failf(data, "Couldn't hyper_request_new");
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(!Curl_use_http_1_1plus(data, conn)) {
|
||||
@@ -947,57 +973,57 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
|
||||
HYPER_HTTP_VERSION_1_0)) {
|
||||
failf(data, "error setting HTTP version");
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if(hyper_request_set_method(req, (uint8_t *)method, strlen(method))) {
|
||||
failf(data, "error setting method");
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = request_target(data, conn, method, req);
|
||||
if(result)
|
||||
goto error;
|
||||
goto out;
|
||||
|
||||
headers = hyper_request_headers(req);
|
||||
if(!headers) {
|
||||
failf(data, "hyper_request_headers");
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = hyper_request_on_informational(req, http1xx_cb, data);
|
||||
if(rc) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(data->state.aptr.host) {
|
||||
result = Curl_hyper_header(data, headers, data->state.aptr.host);
|
||||
if(result)
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
if(data->state.aptr.proxyuserpwd) {
|
||||
result = Curl_hyper_header(data, headers, data->state.aptr.proxyuserpwd);
|
||||
if(result)
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(data->state.aptr.userpwd) {
|
||||
result = Curl_hyper_header(data, headers, data->state.aptr.userpwd);
|
||||
if(result)
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if((data->state.use_range && data->state.aptr.rangeline)) {
|
||||
result = Curl_hyper_header(data, headers, data->state.aptr.rangeline);
|
||||
if(result)
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(data->set.str[STRING_USERAGENT] &&
|
||||
@@ -1005,7 +1031,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
|
||||
data->state.aptr.uagent) {
|
||||
result = Curl_hyper_header(data, headers, data->state.aptr.uagent);
|
||||
if(result)
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
|
||||
p_accept = Curl_checkheaders(data,
|
||||
@@ -1013,12 +1039,12 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
|
||||
if(p_accept) {
|
||||
result = Curl_hyper_header(data, headers, p_accept);
|
||||
if(result)
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
if(te) {
|
||||
result = Curl_hyper_header(data, headers, te);
|
||||
if(result)
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifndef CURL_DISABLE_ALTSVC
|
||||
@@ -1027,11 +1053,11 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
|
||||
conn->conn_to_host.name, conn->conn_to_port);
|
||||
if(!altused) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
result = Curl_hyper_header(data, headers, altused);
|
||||
if(result)
|
||||
goto error;
|
||||
goto out;
|
||||
free(altused);
|
||||
}
|
||||
#endif
|
||||
@@ -1042,7 +1068,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
|
||||
!Curl_checkProxyheaders(data, conn, STRCONST("Proxy-Connection"))) {
|
||||
result = Curl_hyper_header(data, headers, "Proxy-Connection: Keep-Alive");
|
||||
if(result)
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1054,17 +1080,17 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
|
||||
else
|
||||
result = Curl_hyper_header(data, headers, data->state.aptr.ref);
|
||||
if(result)
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBZ
|
||||
/* we only consider transfer-encoding magic if libz support is built-in */
|
||||
result = Curl_transferencode(data);
|
||||
if(result)
|
||||
goto error;
|
||||
goto out;
|
||||
result = Curl_hyper_header(data, headers, data->state.aptr.te);
|
||||
if(result)
|
||||
goto error;
|
||||
goto out;
|
||||
#endif
|
||||
|
||||
if(!Curl_checkheaders(data, STRCONST("Accept-Encoding")) &&
|
||||
@@ -1078,29 +1104,29 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
|
||||
result = Curl_hyper_header(data, headers,
|
||||
data->state.aptr.accept_encoding);
|
||||
if(result)
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
Curl_safefree(data->state.aptr.accept_encoding);
|
||||
|
||||
result = cookies(data, conn, headers);
|
||||
if(result)
|
||||
goto error;
|
||||
goto out;
|
||||
|
||||
if(!result && conn->handler->protocol&(CURLPROTO_WS|CURLPROTO_WSS))
|
||||
result = Curl_ws_request(data, headers);
|
||||
|
||||
result = Curl_add_timecondition(data, headers);
|
||||
if(result)
|
||||
goto error;
|
||||
goto out;
|
||||
|
||||
result = Curl_add_custom_headers(data, FALSE, headers);
|
||||
if(result)
|
||||
goto error;
|
||||
goto out;
|
||||
|
||||
result = finalize_request(data, headers, req, httpreq);
|
||||
if(result)
|
||||
goto error;
|
||||
goto out;
|
||||
|
||||
Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"\r\n", 2);
|
||||
|
||||
@@ -1114,14 +1140,14 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
|
||||
if(!sendtask) {
|
||||
failf(data, "hyper_clientconn_send");
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
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;
|
||||
goto out;
|
||||
}
|
||||
sendtask = NULL; /* ownership passed on */
|
||||
|
||||
@@ -1131,6 +1157,9 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
|
||||
if((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) {
|
||||
/* HTTP GET/HEAD download */
|
||||
Curl_pgrsSetUploadSize(data, 0); /* nothing */
|
||||
result = Curl_req_set_upload_done(data);
|
||||
if(result)
|
||||
goto out;
|
||||
}
|
||||
|
||||
Curl_xfer_setup1(data, CURL_XFER_SENDRECV, -1, TRUE);
|
||||
@@ -1142,24 +1171,20 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
Curl_safefree(data->state.aptr.proxyuserpwd);
|
||||
#endif
|
||||
return CURLE_OK;
|
||||
error:
|
||||
DEBUGASSERT(result);
|
||||
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);
|
||||
|
||||
out:
|
||||
if(result) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
+2
-3
@@ -266,7 +266,7 @@ static CURLcode send_CONNECT(struct Curl_cfilter *cf,
|
||||
blen -= ts->nsent;
|
||||
buf += ts->nsent;
|
||||
|
||||
nwritten = cf->next->cft->do_send(cf->next, data, buf, blen, &result);
|
||||
nwritten = cf->next->cft->do_send(cf->next, data, buf, blen, FALSE, &result);
|
||||
if(nwritten < 0) {
|
||||
if(result == CURLE_AGAIN) {
|
||||
result = CURLE_OK;
|
||||
@@ -489,8 +489,7 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
|
||||
ts->keepon = KEEPON_IGNORE;
|
||||
|
||||
if(ts->cl) {
|
||||
infof(data, "Ignore %" CURL_FORMAT_CURL_OFF_T
|
||||
" bytes of response-body", ts->cl);
|
||||
infof(data, "Ignore %" FMT_OFF_T " bytes of response-body", ts->cl);
|
||||
}
|
||||
else if(ts->chunked_encoding) {
|
||||
infof(data, "Ignore chunked response-body");
|
||||
|
||||
+108
-84
@@ -73,7 +73,6 @@ struct tunnel_stream {
|
||||
char *authority;
|
||||
int32_t stream_id;
|
||||
uint32_t error;
|
||||
size_t upload_blocked_len;
|
||||
h2_tunnel_state state;
|
||||
BIT(has_final_response);
|
||||
BIT(closed);
|
||||
@@ -217,11 +216,13 @@ static void drain_tunnel(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
struct tunnel_stream *tunnel)
|
||||
{
|
||||
struct cf_h2_proxy_ctx *ctx = cf->ctx;
|
||||
unsigned char bits;
|
||||
|
||||
(void)cf;
|
||||
bits = CURL_CSELECT_IN;
|
||||
if(!tunnel->closed && !tunnel->reset && tunnel->upload_blocked_len)
|
||||
if(!tunnel->closed && !tunnel->reset &&
|
||||
!Curl_bufq_is_empty(&ctx->tunnel.sendbuf))
|
||||
bits |= CURL_CSELECT_OUT;
|
||||
if(data->state.select_bits != bits) {
|
||||
CURL_TRC_CF(data, cf, "[%d] DRAIN select_bits=%x",
|
||||
@@ -260,7 +261,7 @@ static ssize_t proxy_h2_nw_out_writer(void *writer_ctx,
|
||||
if(cf) {
|
||||
struct Curl_easy *data = CF_DATA_CURRENT(cf);
|
||||
nwritten = Curl_conn_cf_send(cf->next, data, (const char *)buf, buflen,
|
||||
err);
|
||||
FALSE, err);
|
||||
CURL_TRC_CF(data, cf, "[0] nw_out_writer(len=%zu) -> %zd, %d",
|
||||
buflen, nwritten, *err);
|
||||
}
|
||||
@@ -1079,7 +1080,7 @@ static CURLcode H2_CONNECT(struct Curl_cfilter *cf,
|
||||
} while(ts->state == H2_TUNNEL_INIT);
|
||||
|
||||
out:
|
||||
if(result || ctx->tunnel.closed)
|
||||
if((result && (result != CURLE_AGAIN)) || ctx->tunnel.closed)
|
||||
h2_tunnel_go_state(cf, ts, H2_TUNNEL_FAILED, data);
|
||||
return result;
|
||||
}
|
||||
@@ -1185,7 +1186,8 @@ static CURLcode cf_h2_proxy_shutdown(struct Curl_cfilter *cf,
|
||||
if(!ctx->sent_goaway) {
|
||||
rv = nghttp2_submit_goaway(ctx->h2, NGHTTP2_FLAG_NONE,
|
||||
0, 0,
|
||||
(const uint8_t *)"shutown", sizeof("shutown"));
|
||||
(const uint8_t *)"shutdown",
|
||||
sizeof("shutdown"));
|
||||
if(rv) {
|
||||
failf(data, "nghttp2_submit_goaway() failed: %s(%d)",
|
||||
nghttp2_strerror(rv), rv);
|
||||
@@ -1231,7 +1233,9 @@ static void cf_h2_proxy_adjust_pollset(struct Curl_cfilter *cf,
|
||||
bool want_recv, want_send;
|
||||
|
||||
if(!cf->connected && ctx->h2) {
|
||||
want_send = nghttp2_session_want_write(ctx->h2);
|
||||
want_send = nghttp2_session_want_write(ctx->h2) ||
|
||||
!Curl_bufq_is_empty(&ctx->outbufq) ||
|
||||
!Curl_bufq_is_empty(&ctx->tunnel.sendbuf);
|
||||
want_recv = nghttp2_session_want_read(ctx->h2);
|
||||
}
|
||||
else
|
||||
@@ -1247,17 +1251,25 @@ static void cf_h2_proxy_adjust_pollset(struct Curl_cfilter *cf,
|
||||
ctx->h2, ctx->tunnel.stream_id);
|
||||
want_recv = (want_recv || c_exhaust || s_exhaust);
|
||||
want_send = (!s_exhaust && want_send) ||
|
||||
(!c_exhaust && nghttp2_session_want_write(ctx->h2));
|
||||
(!c_exhaust && nghttp2_session_want_write(ctx->h2)) ||
|
||||
!Curl_bufq_is_empty(&ctx->outbufq) ||
|
||||
!Curl_bufq_is_empty(&ctx->tunnel.sendbuf);
|
||||
|
||||
Curl_pollset_set(data, ps, sock, want_recv, want_send);
|
||||
CURL_TRC_CF(data, cf, "adjust_pollset, want_recv=%d want_send=%d",
|
||||
want_recv, want_send);
|
||||
CF_DATA_RESTORE(cf, save);
|
||||
}
|
||||
else if(ctx->sent_goaway && !cf->shutdown) {
|
||||
/* shutdown in progress */
|
||||
CF_DATA_SAVE(save, cf, data);
|
||||
want_send = nghttp2_session_want_write(ctx->h2);
|
||||
want_send = nghttp2_session_want_write(ctx->h2) ||
|
||||
!Curl_bufq_is_empty(&ctx->outbufq) ||
|
||||
!Curl_bufq_is_empty(&ctx->tunnel.sendbuf);
|
||||
want_recv = nghttp2_session_want_read(ctx->h2);
|
||||
Curl_pollset_set(data, ps, sock, want_recv, want_send);
|
||||
CURL_TRC_CF(data, cf, "adjust_pollset, want_recv=%d want_send=%d",
|
||||
want_recv, want_send);
|
||||
CF_DATA_RESTORE(cf, save);
|
||||
}
|
||||
}
|
||||
@@ -1364,16 +1376,7 @@ static ssize_t cf_h2_proxy_recv(struct Curl_cfilter *cf,
|
||||
}
|
||||
|
||||
result = proxy_h2_progress_egress(cf, data);
|
||||
if(result == CURLE_AGAIN) {
|
||||
/* pending data to send, need to be called again. Ideally, we would
|
||||
* monitor the socket for POLLOUT, but we might not be in SENDING
|
||||
* transfer state any longer and are unable to make this happen.
|
||||
*/
|
||||
CURL_TRC_CF(data, cf, "[%d] egress blocked, DRAIN",
|
||||
ctx->tunnel.stream_id);
|
||||
drain_tunnel(cf, data, &ctx->tunnel);
|
||||
}
|
||||
else if(result) {
|
||||
if(result && (result != CURLE_AGAIN)) {
|
||||
*err = result;
|
||||
nread = -1;
|
||||
}
|
||||
@@ -1393,15 +1396,16 @@ out:
|
||||
|
||||
static ssize_t cf_h2_proxy_send(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
const void *buf, size_t len, CURLcode *err)
|
||||
const void *buf, size_t len, bool eos,
|
||||
CURLcode *err)
|
||||
{
|
||||
struct cf_h2_proxy_ctx *ctx = cf->ctx;
|
||||
struct cf_call_data save;
|
||||
int rv;
|
||||
ssize_t nwritten;
|
||||
CURLcode result;
|
||||
int blocked = 0;
|
||||
|
||||
(void)eos; /* TODO, maybe useful for blocks? */
|
||||
if(ctx->tunnel.state != H2_TUNNEL_ESTABLISHED) {
|
||||
*err = CURLE_SEND_ERROR;
|
||||
return -1;
|
||||
@@ -1413,29 +1417,10 @@ static ssize_t cf_h2_proxy_send(struct Curl_cfilter *cf,
|
||||
*err = CURLE_SEND_ERROR;
|
||||
goto out;
|
||||
}
|
||||
else if(ctx->tunnel.upload_blocked_len) {
|
||||
/* the data in `buf` has already been submitted or added to the
|
||||
* buffers, but have been EAGAINed on the last invocation. */
|
||||
DEBUGASSERT(len >= ctx->tunnel.upload_blocked_len);
|
||||
if(len < ctx->tunnel.upload_blocked_len) {
|
||||
/* Did we get called again with a smaller `len`? This should not
|
||||
* happen. We are not prepared to handle that. */
|
||||
failf(data, "HTTP/2 proxy, send again with decreased length");
|
||||
*err = CURLE_HTTP2;
|
||||
nwritten = -1;
|
||||
goto out;
|
||||
}
|
||||
nwritten = (ssize_t)ctx->tunnel.upload_blocked_len;
|
||||
ctx->tunnel.upload_blocked_len = 0;
|
||||
*err = CURLE_OK;
|
||||
}
|
||||
else {
|
||||
nwritten = Curl_bufq_write(&ctx->tunnel.sendbuf, buf, len, err);
|
||||
if(nwritten < 0) {
|
||||
if(*err != CURLE_AGAIN)
|
||||
goto out;
|
||||
nwritten = 0;
|
||||
}
|
||||
if(nwritten < 0 && (*err != CURLE_AGAIN))
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(!Curl_bufq_is_empty(&ctx->tunnel.sendbuf)) {
|
||||
@@ -1458,52 +1443,13 @@ static ssize_t cf_h2_proxy_send(struct Curl_cfilter *cf,
|
||||
/* Call the nghttp2 send loop and flush to write ALL buffered data,
|
||||
* headers and/or request body completely out to the network */
|
||||
result = proxy_h2_progress_egress(cf, data);
|
||||
if(result == CURLE_AGAIN) {
|
||||
blocked = 1;
|
||||
}
|
||||
else if(result) {
|
||||
if(result && (result != CURLE_AGAIN)) {
|
||||
*err = result;
|
||||
nwritten = -1;
|
||||
goto out;
|
||||
}
|
||||
else if(!Curl_bufq_is_empty(&ctx->tunnel.sendbuf)) {
|
||||
/* although we wrote everything that nghttp2 wants to send now,
|
||||
* there is data left in our stream send buffer unwritten. This may
|
||||
* be due to the stream's HTTP/2 flow window being exhausted. */
|
||||
blocked = 1;
|
||||
}
|
||||
|
||||
if(blocked) {
|
||||
/* Unable to send all data, due to connection blocked or H2 window
|
||||
* exhaustion. Data is left in our stream buffer, or nghttp2's internal
|
||||
* frame buffer or our network out buffer. */
|
||||
size_t rwin = (size_t)nghttp2_session_get_stream_remote_window_size(
|
||||
ctx->h2, ctx->tunnel.stream_id);
|
||||
if(rwin == 0) {
|
||||
/* H2 flow window exhaustion.
|
||||
* FIXME: there is no way to HOLD all transfers that use this
|
||||
* proxy connection AND to UNHOLD all of them again when the
|
||||
* window increases.
|
||||
* We *could* iterate over all data on this conn maybe? */
|
||||
CURL_TRC_CF(data, cf, "[%d] remote flow "
|
||||
"window is exhausted", ctx->tunnel.stream_id);
|
||||
}
|
||||
|
||||
/* Whatever the cause, we need to return CURL_EAGAIN for this call.
|
||||
* We have unwritten state that needs us being invoked again and EAGAIN
|
||||
* is the only way to ensure that. */
|
||||
ctx->tunnel.upload_blocked_len = nwritten;
|
||||
CURL_TRC_CF(data, cf, "[%d] cf_send(len=%zu) BLOCK: win %u/%zu "
|
||||
"blocked_len=%zu",
|
||||
ctx->tunnel.stream_id, len,
|
||||
nghttp2_session_get_remote_window_size(ctx->h2), rwin,
|
||||
nwritten);
|
||||
drain_tunnel(cf, data, &ctx->tunnel);
|
||||
*err = CURLE_AGAIN;
|
||||
nwritten = -1;
|
||||
goto out;
|
||||
}
|
||||
else if(proxy_h2_should_close_session(ctx)) {
|
||||
if(proxy_h2_should_close_session(ctx)) {
|
||||
/* nghttp2 thinks this session is done. If the stream has not been
|
||||
* closed, this is an error state for out transfer */
|
||||
if(ctx->tunnel.closed) {
|
||||
@@ -1536,6 +1482,38 @@ out:
|
||||
return nwritten;
|
||||
}
|
||||
|
||||
static CURLcode cf_h2_proxy_flush(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
struct cf_h2_proxy_ctx *ctx = cf->ctx;
|
||||
struct cf_call_data save;
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
CF_DATA_SAVE(save, cf, data);
|
||||
if(!Curl_bufq_is_empty(&ctx->tunnel.sendbuf)) {
|
||||
/* resume the potentially suspended tunnel */
|
||||
int rv = nghttp2_session_resume_data(ctx->h2, ctx->tunnel.stream_id);
|
||||
if(nghttp2_is_fatal(rv)) {
|
||||
result = CURLE_SEND_ERROR;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
result = proxy_h2_progress_egress(cf, data);
|
||||
|
||||
out:
|
||||
CURL_TRC_CF(data, cf, "[%d] flush -> %d, "
|
||||
"h2 windows %d-%d (stream-conn), buffers %zu-%zu (stream-conn)",
|
||||
ctx->tunnel.stream_id, result,
|
||||
nghttp2_session_get_stream_remote_window_size(
|
||||
ctx->h2, ctx->tunnel.stream_id),
|
||||
nghttp2_session_get_remote_window_size(ctx->h2),
|
||||
Curl_bufq_len(&ctx->tunnel.sendbuf),
|
||||
Curl_bufq_len(&ctx->outbufq));
|
||||
CF_DATA_RESTORE(cf, save);
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool proxy_h2_connisalive(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool *input_pending)
|
||||
@@ -1589,6 +1567,52 @@ static bool cf_h2_proxy_is_alive(struct Curl_cfilter *cf,
|
||||
return result;
|
||||
}
|
||||
|
||||
static CURLcode cf_h2_proxy_query(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
int query, int *pres1, void *pres2)
|
||||
{
|
||||
struct cf_h2_proxy_ctx *ctx = cf->ctx;
|
||||
|
||||
switch(query) {
|
||||
case CF_QUERY_NEED_FLUSH: {
|
||||
if(!Curl_bufq_is_empty(&ctx->outbufq) ||
|
||||
!Curl_bufq_is_empty(&ctx->tunnel.sendbuf)) {
|
||||
CURL_TRC_CF(data, cf, "needs flush");
|
||||
*pres1 = TRUE;
|
||||
return CURLE_OK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return cf->next?
|
||||
cf->next->cft->query(cf->next, data, query, pres1, pres2) :
|
||||
CURLE_UNKNOWN_OPTION;
|
||||
}
|
||||
|
||||
static CURLcode cf_h2_proxy_cntrl(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
int event, int arg1, void *arg2)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct cf_call_data save;
|
||||
|
||||
(void)arg1;
|
||||
(void)arg2;
|
||||
|
||||
switch(event) {
|
||||
case CF_CTRL_FLUSH:
|
||||
CF_DATA_SAVE(save, cf, data);
|
||||
result = cf_h2_proxy_flush(cf, data);
|
||||
CF_DATA_RESTORE(cf, save);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
struct Curl_cftype Curl_cft_h2_proxy = {
|
||||
"H2-PROXY",
|
||||
CF_TYPE_IP_CONNECT|CF_TYPE_PROXY,
|
||||
@@ -1602,10 +1626,10 @@ struct Curl_cftype Curl_cft_h2_proxy = {
|
||||
cf_h2_proxy_data_pending,
|
||||
cf_h2_proxy_send,
|
||||
cf_h2_proxy_recv,
|
||||
Curl_cf_def_cntrl,
|
||||
cf_h2_proxy_cntrl,
|
||||
cf_h2_proxy_is_alive,
|
||||
Curl_cf_def_conn_keep_alive,
|
||||
Curl_cf_def_query,
|
||||
cf_h2_proxy_query,
|
||||
};
|
||||
|
||||
CURLcode Curl_cf_h2_proxy_insert_after(struct Curl_cfilter *cf,
|
||||
|
||||
+19
-17
@@ -70,8 +70,9 @@ static CURLcode cf_haproxy_date_out_set(struct Curl_cfilter*cf,
|
||||
{
|
||||
struct cf_haproxy_ctx *ctx = cf->ctx;
|
||||
CURLcode result;
|
||||
const char *tcp_version;
|
||||
const char *client_ip;
|
||||
struct ip_quadruple ipquad;
|
||||
int is_ipv6;
|
||||
|
||||
DEBUGASSERT(ctx);
|
||||
DEBUGASSERT(ctx->state == HAPROXY_INIT);
|
||||
@@ -81,19 +82,20 @@ static CURLcode cf_haproxy_date_out_set(struct Curl_cfilter*cf,
|
||||
result = Curl_dyn_addn(&ctx->data_out, STRCONST("PROXY UNKNOWN\r\n"));
|
||||
else {
|
||||
#endif /* USE_UNIX_SOCKETS */
|
||||
result = Curl_conn_cf_get_ip_info(cf->next, data, &is_ipv6, &ipquad);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
/* Emit the correct prefix for IPv6 */
|
||||
tcp_version = cf->conn->bits.ipv6 ? "TCP6" : "TCP4";
|
||||
if(data->set.str[STRING_HAPROXY_CLIENT_IP])
|
||||
client_ip = data->set.str[STRING_HAPROXY_CLIENT_IP];
|
||||
else
|
||||
client_ip = data->info.primary.local_ip;
|
||||
client_ip = ipquad.local_ip;
|
||||
|
||||
result = Curl_dyn_addf(&ctx->data_out, "PROXY %s %s %s %i %i\r\n",
|
||||
tcp_version,
|
||||
client_ip,
|
||||
data->info.primary.remote_ip,
|
||||
data->info.primary.local_port,
|
||||
data->info.primary.remote_port);
|
||||
is_ipv6? "TCP6" : "TCP4",
|
||||
client_ip, ipquad.remote_ip,
|
||||
ipquad.local_port, ipquad.remote_port);
|
||||
|
||||
#ifdef USE_UNIX_SOCKETS
|
||||
}
|
||||
@@ -129,17 +131,17 @@ static CURLcode cf_haproxy_connect(struct Curl_cfilter *cf,
|
||||
case HAPROXY_SEND:
|
||||
len = Curl_dyn_len(&ctx->data_out);
|
||||
if(len > 0) {
|
||||
size_t written;
|
||||
result = Curl_conn_send(data, cf->sockindex,
|
||||
Curl_dyn_ptr(&ctx->data_out),
|
||||
len, &written);
|
||||
if(result == CURLE_AGAIN) {
|
||||
ssize_t nwritten;
|
||||
nwritten = Curl_conn_cf_send(cf->next, data,
|
||||
Curl_dyn_ptr(&ctx->data_out), len, FALSE,
|
||||
&result);
|
||||
if(nwritten < 0) {
|
||||
if(result != CURLE_AGAIN)
|
||||
goto out;
|
||||
result = CURLE_OK;
|
||||
written = 0;
|
||||
nwritten = 0;
|
||||
}
|
||||
else if(result)
|
||||
goto out;
|
||||
Curl_dyn_tail(&ctx->data_out, len - written);
|
||||
Curl_dyn_tail(&ctx->data_out, len - (size_t)nwritten);
|
||||
if(Curl_dyn_len(&ctx->data_out) > 0) {
|
||||
result = CURLE_OK;
|
||||
goto out;
|
||||
|
||||
+43
-6
@@ -96,6 +96,21 @@ static bool cf_hc_baller_data_pending(struct cf_hc_baller *b,
|
||||
return b->cf && !b->result && b->cf->cft->has_data_pending(b->cf, data);
|
||||
}
|
||||
|
||||
static bool cf_hc_baller_needs_flush(struct cf_hc_baller *b,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
return b->cf && !b->result && Curl_conn_cf_needs_flush(b->cf, data);
|
||||
}
|
||||
|
||||
static CURLcode cf_hc_baller_cntrl(struct cf_hc_baller *b,
|
||||
struct Curl_easy *data,
|
||||
int event, int arg1, void *arg2)
|
||||
{
|
||||
if(b->cf && !b->result)
|
||||
return Curl_conn_cf_cntrl(b->cf, data, FALSE, event, arg1, arg2);
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
struct cf_hc_ctx {
|
||||
cf_hc_state state;
|
||||
const struct Curl_dns_entry *remotehost;
|
||||
@@ -174,7 +189,6 @@ static CURLcode baller_connected(struct Curl_cfilter *cf,
|
||||
|
||||
switch(cf->conn->alpn) {
|
||||
case CURL_HTTP_VERSION_3:
|
||||
infof(data, "using HTTP/3");
|
||||
break;
|
||||
case CURL_HTTP_VERSION_2:
|
||||
#ifdef USE_NGHTTP2
|
||||
@@ -187,16 +201,12 @@ static CURLcode baller_connected(struct Curl_cfilter *cf,
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
infof(data, "using HTTP/2");
|
||||
break;
|
||||
default:
|
||||
infof(data, "using HTTP/1.x");
|
||||
break;
|
||||
}
|
||||
ctx->state = CF_HC_SUCCESS;
|
||||
cf->connected = TRUE;
|
||||
Curl_conn_cf_cntrl(cf->next, data, TRUE,
|
||||
CF_CTRL_CONN_INFO_UPDATE, 0, NULL);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -428,6 +438,8 @@ static CURLcode cf_hc_query(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
int query, int *pres1, void *pres2)
|
||||
{
|
||||
struct cf_hc_ctx *ctx = cf->ctx;
|
||||
|
||||
if(!cf->connected) {
|
||||
switch(query) {
|
||||
case CF_QUERY_TIMER_CONNECT: {
|
||||
@@ -440,6 +452,14 @@ static CURLcode cf_hc_query(struct Curl_cfilter *cf,
|
||||
*when = cf_get_max_baller_time(cf, data, CF_QUERY_TIMER_APPCONNECT);
|
||||
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;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -449,6 +469,23 @@ static CURLcode cf_hc_query(struct Curl_cfilter *cf,
|
||||
CURLE_UNKNOWN_OPTION;
|
||||
}
|
||||
|
||||
static CURLcode cf_hc_cntrl(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
int event, int arg1, void *arg2)
|
||||
{
|
||||
struct cf_hc_ctx *ctx = cf->ctx;
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
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;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void cf_hc_close(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
{
|
||||
CURL_TRC_CF(data, cf, "close");
|
||||
@@ -484,7 +521,7 @@ struct Curl_cftype Curl_cft_http_connect = {
|
||||
cf_hc_data_pending,
|
||||
Curl_cf_def_send,
|
||||
Curl_cf_def_recv,
|
||||
Curl_cf_def_cntrl,
|
||||
cf_hc_cntrl,
|
||||
Curl_cf_def_conn_is_alive,
|
||||
Curl_cf_def_conn_keep_alive,
|
||||
cf_hc_query,
|
||||
|
||||
+96
-52
@@ -124,7 +124,7 @@ static void tcpnodelay(struct Curl_easy *data, curl_socket_t sockfd)
|
||||
}
|
||||
|
||||
#ifdef SO_NOSIGPIPE
|
||||
/* The preferred method on Mac OS X (10.2 and later) to prevent SIGPIPEs when
|
||||
/* The preferred method on macOS (10.2 and later) to prevent SIGPIPEs when
|
||||
sending data to a dead peer (instead of relying on the 4th argument to send
|
||||
being MSG_NOSIGNAL). Possibly also existing and in use on other BSD
|
||||
systems? */
|
||||
@@ -146,7 +146,13 @@ static void nosigpipe(struct Curl_easy *data,
|
||||
#define nosigpipe(x,y) Curl_nop_stmt
|
||||
#endif
|
||||
|
||||
#if defined(USE_WINSOCK) || \
|
||||
#if defined(USE_WINSOCK) && \
|
||||
defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL) && defined(TCP_KEEPCNT)
|
||||
/* Win 10, v 1709 (10.0.16299) and later can use SetSockOpt TCP_KEEP____
|
||||
* so should use seconds */
|
||||
#define CURL_WINSOCK_KEEP_SSO
|
||||
#define KEEPALIVE_FACTOR(x)
|
||||
#elif defined(USE_WINSOCK) || \
|
||||
(defined(__sun) && !defined(TCP_KEEPIDLE)) || \
|
||||
(defined(__DragonFly__) && __DragonFly_version < 500702) || \
|
||||
(defined(_WIN32) && !defined(TCP_KEEPIDLE))
|
||||
@@ -177,19 +183,19 @@ tcpkeepalive(struct Curl_easy *data,
|
||||
if(setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE,
|
||||
(void *)&optval, sizeof(optval)) < 0) {
|
||||
infof(data, "Failed to set SO_KEEPALIVE on fd "
|
||||
"%" CURL_FORMAT_SOCKET_T ": errno %d",
|
||||
"%" FMT_SOCKET_T ": errno %d",
|
||||
sockfd, SOCKERRNO);
|
||||
}
|
||||
else {
|
||||
#if defined(SIO_KEEPALIVE_VALS) /* Windows */
|
||||
/* Windows 10, version 1709 (10.0.16299) and later versions */
|
||||
#if defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL) && defined(TCP_KEEPCNT)
|
||||
#if defined(CURL_WINSOCK_KEEP_SSO)
|
||||
optval = curlx_sltosi(data->set.tcp_keepidle);
|
||||
KEEPALIVE_FACTOR(optval);
|
||||
if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE,
|
||||
(const char *)&optval, sizeof(optval)) < 0) {
|
||||
infof(data, "Failed to set TCP_KEEPIDLE on fd "
|
||||
"%" CURL_FORMAT_SOCKET_T ": errno %d",
|
||||
"%" FMT_SOCKET_T ": errno %d",
|
||||
sockfd, SOCKERRNO);
|
||||
}
|
||||
optval = curlx_sltosi(data->set.tcp_keepintvl);
|
||||
@@ -197,14 +203,14 @@ tcpkeepalive(struct Curl_easy *data,
|
||||
if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL,
|
||||
(const char *)&optval, sizeof(optval)) < 0) {
|
||||
infof(data, "Failed to set TCP_KEEPINTVL on fd "
|
||||
"%" CURL_FORMAT_SOCKET_T ": errno %d",
|
||||
"%" FMT_SOCKET_T ": errno %d",
|
||||
sockfd, SOCKERRNO);
|
||||
}
|
||||
optval = curlx_sltosi(data->set.tcp_keepcnt);
|
||||
if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPCNT,
|
||||
(const char *)&optval, sizeof(optval)) < 0) {
|
||||
infof(data, "Failed to set TCP_KEEPCNT on fd "
|
||||
"%" CURL_FORMAT_SOCKET_T ": errno %d",
|
||||
"%" FMT_SOCKET_T ": errno %d",
|
||||
sockfd, SOCKERRNO);
|
||||
}
|
||||
#else /* Windows < 10.0.16299 */
|
||||
@@ -220,8 +226,7 @@ tcpkeepalive(struct Curl_easy *data,
|
||||
if(WSAIoctl(sockfd, SIO_KEEPALIVE_VALS, (LPVOID) &vals, sizeof(vals),
|
||||
NULL, 0, &dummy, NULL, NULL) != 0) {
|
||||
infof(data, "Failed to set SIO_KEEPALIVE_VALS on fd "
|
||||
"%" CURL_FORMAT_SOCKET_T ": errno %d",
|
||||
sockfd, SOCKERRNO);
|
||||
"%" FMT_SOCKET_T ": errno %d", sockfd, SOCKERRNO);
|
||||
}
|
||||
#endif
|
||||
#else /* !Windows */
|
||||
@@ -231,17 +236,17 @@ tcpkeepalive(struct Curl_easy *data,
|
||||
if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE,
|
||||
(void *)&optval, sizeof(optval)) < 0) {
|
||||
infof(data, "Failed to set TCP_KEEPIDLE on fd "
|
||||
"%" CURL_FORMAT_SOCKET_T ": errno %d",
|
||||
"%" FMT_SOCKET_T ": errno %d",
|
||||
sockfd, SOCKERRNO);
|
||||
}
|
||||
#elif defined(TCP_KEEPALIVE)
|
||||
/* Mac OS X style */
|
||||
/* macOS style */
|
||||
optval = curlx_sltosi(data->set.tcp_keepidle);
|
||||
KEEPALIVE_FACTOR(optval);
|
||||
if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE,
|
||||
(void *)&optval, sizeof(optval)) < 0) {
|
||||
infof(data, "Failed to set TCP_KEEPALIVE on fd "
|
||||
"%" CURL_FORMAT_SOCKET_T ": errno %d",
|
||||
"%" FMT_SOCKET_T ": errno %d",
|
||||
sockfd, SOCKERRNO);
|
||||
}
|
||||
#elif defined(TCP_KEEPALIVE_THRESHOLD)
|
||||
@@ -251,7 +256,7 @@ tcpkeepalive(struct Curl_easy *data,
|
||||
if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE_THRESHOLD,
|
||||
(void *)&optval, sizeof(optval)) < 0) {
|
||||
infof(data, "Failed to set TCP_KEEPALIVE_THRESHOLD on fd "
|
||||
"%" CURL_FORMAT_SOCKET_T ": errno %d",
|
||||
"%" FMT_SOCKET_T ": errno %d",
|
||||
sockfd, SOCKERRNO);
|
||||
}
|
||||
#endif
|
||||
@@ -261,7 +266,7 @@ tcpkeepalive(struct Curl_easy *data,
|
||||
if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL,
|
||||
(void *)&optval, sizeof(optval)) < 0) {
|
||||
infof(data, "Failed to set TCP_KEEPINTVL on fd "
|
||||
"%" CURL_FORMAT_SOCKET_T ": errno %d",
|
||||
"%" FMT_SOCKET_T ": errno %d",
|
||||
sockfd, SOCKERRNO);
|
||||
}
|
||||
#elif defined(TCP_KEEPALIVE_ABORT_THRESHOLD)
|
||||
@@ -282,8 +287,7 @@ tcpkeepalive(struct Curl_easy *data,
|
||||
if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE_ABORT_THRESHOLD,
|
||||
(void *)&optval, sizeof(optval)) < 0) {
|
||||
infof(data, "Failed to set TCP_KEEPALIVE_ABORT_THRESHOLD on fd "
|
||||
"%" CURL_FORMAT_SOCKET_T ": errno %d",
|
||||
sockfd, SOCKERRNO);
|
||||
"%" FMT_SOCKET_T ": errno %d", sockfd, SOCKERRNO);
|
||||
}
|
||||
#endif
|
||||
#ifdef TCP_KEEPCNT
|
||||
@@ -291,8 +295,7 @@ tcpkeepalive(struct Curl_easy *data,
|
||||
if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPCNT,
|
||||
(void *)&optval, sizeof(optval)) < 0) {
|
||||
infof(data, "Failed to set TCP_KEEPCNT on fd "
|
||||
"%" CURL_FORMAT_SOCKET_T ": errno %d",
|
||||
sockfd, SOCKERRNO);
|
||||
"%" FMT_SOCKET_T ": errno %d", sockfd, SOCKERRNO);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -404,6 +407,9 @@ CURLcode Curl_socket_open(struct Curl_easy *data,
|
||||
static int socket_close(struct Curl_easy *data, struct connectdata *conn,
|
||||
int use_callback, curl_socket_t sock)
|
||||
{
|
||||
if(CURL_SOCKET_BAD == sock)
|
||||
return 0;
|
||||
|
||||
if(use_callback && conn && conn->fclosesocket) {
|
||||
int rc;
|
||||
Curl_multi_closed(data, sock);
|
||||
@@ -502,32 +508,37 @@ void Curl_sndbuf_init(curl_socket_t sockfd)
|
||||
*
|
||||
* Returns CURLE_OK on success.
|
||||
*/
|
||||
CURLcode Curl_parse_interface(const char *input, size_t len,
|
||||
CURLcode Curl_parse_interface(const char *input,
|
||||
char **dev, char **iface, char **host)
|
||||
{
|
||||
static const char if_prefix[] = "if!";
|
||||
static const char host_prefix[] = "host!";
|
||||
static const char if_host_prefix[] = "ifhost!";
|
||||
size_t len;
|
||||
|
||||
DEBUGASSERT(dev);
|
||||
DEBUGASSERT(iface);
|
||||
DEBUGASSERT(host);
|
||||
|
||||
if(strncmp(if_prefix, input, strlen(if_prefix)) == 0) {
|
||||
len = strlen(input);
|
||||
if(len > 512)
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
|
||||
if(!strncmp(if_prefix, input, strlen(if_prefix))) {
|
||||
input += strlen(if_prefix);
|
||||
if(!*input)
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
*iface = Curl_memdup0(input, len - strlen(if_prefix));
|
||||
return *iface ? CURLE_OK : CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
if(strncmp(host_prefix, input, strlen(host_prefix)) == 0) {
|
||||
else if(!strncmp(host_prefix, input, strlen(host_prefix))) {
|
||||
input += strlen(host_prefix);
|
||||
if(!*input)
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
*host = Curl_memdup0(input, len - strlen(host_prefix));
|
||||
return *host ? CURLE_OK : CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
if(strncmp(if_host_prefix, input, strlen(if_host_prefix)) == 0) {
|
||||
else if(!strncmp(if_host_prefix, input, strlen(if_host_prefix))) {
|
||||
const char *host_part;
|
||||
input += strlen(if_host_prefix);
|
||||
len -= strlen(if_host_prefix);
|
||||
@@ -679,12 +690,13 @@ static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn,
|
||||
conn->ip_version = ipver;
|
||||
|
||||
if(h) {
|
||||
int h_af = h->addr->ai_family;
|
||||
/* convert the resolved address, sizeof myhost >= INET_ADDRSTRLEN */
|
||||
Curl_printable_address(h->addr, myhost, sizeof(myhost));
|
||||
infof(data, "Name '%s' family %i resolved to '%s' family %i",
|
||||
host, af, myhost, h->addr->ai_family);
|
||||
Curl_resolv_unlock(data, h);
|
||||
if(af != h->addr->ai_family) {
|
||||
host, af, myhost, h_af);
|
||||
Curl_resolv_unlink(data, &h); /* this will NULL, potential free h */
|
||||
if(af != h_af) {
|
||||
/* bad IP version combo, signal the caller to try another address
|
||||
family if available */
|
||||
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||
@@ -694,7 +706,7 @@ static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn,
|
||||
else {
|
||||
/*
|
||||
* provided dev was no interface (or interfaces are not supported
|
||||
* e.g. solaris) no ip address and no domain we fail here
|
||||
* e.g. Solaris) no ip address and no domain we fail here
|
||||
*/
|
||||
done = -1;
|
||||
}
|
||||
@@ -843,7 +855,7 @@ static bool verifyconnect(curl_socket_t sockfd, int *error)
|
||||
if(0 != getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize))
|
||||
err = SOCKERRNO;
|
||||
#ifdef _WIN32_WCE
|
||||
/* Old WinCE versions do not support SO_ERROR */
|
||||
/* Old Windows CE versions do not support SO_ERROR */
|
||||
if(WSAENOPROTOOPT == err) {
|
||||
SET_SOCKERRNO(0);
|
||||
err = 0;
|
||||
@@ -938,6 +950,7 @@ struct cf_socket_ctx {
|
||||
size_t recv_max; /* max enforced read size */
|
||||
#endif
|
||||
BIT(got_first_byte); /* if first byte was received */
|
||||
BIT(listening); /* socket is listening */
|
||||
BIT(accepted); /* socket was accepted, not connected */
|
||||
BIT(sock_connected); /* socket is "connected", e.g. in UDP */
|
||||
BIT(active);
|
||||
@@ -986,8 +999,7 @@ static void cf_socket_close(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
struct cf_socket_ctx *ctx = cf->ctx;
|
||||
|
||||
if(ctx && CURL_SOCKET_BAD != ctx->sock) {
|
||||
CURL_TRC_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
|
||||
")", ctx->sock);
|
||||
CURL_TRC_CF(data, cf, "cf_socket_close(%" FMT_SOCKET_T ")", ctx->sock);
|
||||
if(ctx->sock == cf->conn->sock[cf->sockindex])
|
||||
cf->conn->sock[cf->sockindex] = CURL_SOCKET_BAD;
|
||||
socket_close(data, cf->conn, !ctx->accepted, ctx->sock);
|
||||
@@ -1009,8 +1021,7 @@ static CURLcode cf_socket_shutdown(struct Curl_cfilter *cf,
|
||||
if(cf->connected) {
|
||||
struct cf_socket_ctx *ctx = cf->ctx;
|
||||
|
||||
CURL_TRC_CF(data, cf, "cf_socket_shutdown(%" CURL_FORMAT_SOCKET_T
|
||||
")", ctx->sock);
|
||||
CURL_TRC_CF(data, cf, "cf_socket_shutdown(%" FMT_SOCKET_T ")", ctx->sock);
|
||||
/* On TCP, and when the socket looks well and non-blocking mode
|
||||
* can be enabled, receive dangling bytes before close to avoid
|
||||
* entering RST states unnecessarily. */
|
||||
@@ -1220,7 +1231,7 @@ out:
|
||||
ctx->connected_at = Curl_now();
|
||||
cf->connected = TRUE;
|
||||
}
|
||||
CURL_TRC_CF(data, cf, "cf_socket_open() -> %d, fd=%" CURL_FORMAT_SOCKET_T,
|
||||
CURL_TRC_CF(data, cf, "cf_socket_open() -> %d, fd=%" FMT_SOCKET_T,
|
||||
result, ctx->sock);
|
||||
return result;
|
||||
}
|
||||
@@ -1262,8 +1273,8 @@ static int do_connect(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
#elif defined(TCP_FASTOPEN_CONNECT) /* Linux >= 4.11 */
|
||||
if(setsockopt(ctx->sock, IPPROTO_TCP, TCP_FASTOPEN_CONNECT,
|
||||
(void *)&optval, sizeof(optval)) < 0)
|
||||
infof(data, "Failed to enable TCP Fast Open on fd %"
|
||||
CURL_FORMAT_SOCKET_T, ctx->sock);
|
||||
infof(data, "Failed to enable TCP Fast Open on fd %" FMT_SOCKET_T,
|
||||
ctx->sock);
|
||||
|
||||
rc = connect(ctx->sock, &ctx->addr.sa_addr, ctx->addr.addrlen);
|
||||
#elif defined(MSG_FASTOPEN) /* old Linux */
|
||||
@@ -1398,15 +1409,24 @@ static void cf_socket_adjust_pollset(struct Curl_cfilter *cf,
|
||||
struct cf_socket_ctx *ctx = cf->ctx;
|
||||
|
||||
if(ctx->sock != CURL_SOCKET_BAD) {
|
||||
if(!cf->connected) {
|
||||
/* A listening socket filter needs to be connected before the accept
|
||||
* for some weird FTP interaction. This should be rewritten, so that
|
||||
* FTP no longer does the socket checks and accept calls and delegates
|
||||
* all that to the filter. TODO. */
|
||||
if(ctx->listening) {
|
||||
Curl_pollset_set_in_only(data, ps, ctx->sock);
|
||||
CURL_TRC_CF(data, cf, "adjust_pollset, listening, POLLIN fd=%"
|
||||
FMT_SOCKET_T, ctx->sock);
|
||||
}
|
||||
else if(!cf->connected) {
|
||||
Curl_pollset_set_out_only(data, ps, ctx->sock);
|
||||
CURL_TRC_CF(data, cf, "adjust_pollset, !connected, POLLOUT fd=%"
|
||||
CURL_FORMAT_SOCKET_T, ctx->sock);
|
||||
FMT_SOCKET_T, ctx->sock);
|
||||
}
|
||||
else if(!ctx->active) {
|
||||
Curl_pollset_add_in(data, ps, ctx->sock);
|
||||
CURL_TRC_CF(data, cf, "adjust_pollset, !active, POLLIN fd=%"
|
||||
CURL_FORMAT_SOCKET_T, ctx->sock);
|
||||
FMT_SOCKET_T, ctx->sock);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1449,13 +1469,15 @@ static void win_update_sndbuf_size(struct cf_socket_ctx *ctx)
|
||||
#endif /* USE_WINSOCK */
|
||||
|
||||
static ssize_t cf_socket_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
const void *buf, size_t len, CURLcode *err)
|
||||
const void *buf, size_t len, bool eos,
|
||||
CURLcode *err)
|
||||
{
|
||||
struct cf_socket_ctx *ctx = cf->ctx;
|
||||
curl_socket_t fdsave;
|
||||
ssize_t nwritten;
|
||||
size_t orig_len = len;
|
||||
|
||||
(void)eos; /* unused */
|
||||
*err = CURLE_OK;
|
||||
fdsave = cf->conn->sock[cf->sockindex];
|
||||
cf->conn->sock[cf->sockindex] = ctx->sock;
|
||||
@@ -1464,7 +1486,7 @@ static ssize_t cf_socket_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
/* simulate network blocking/partial writes */
|
||||
if(ctx->wblock_percent > 0) {
|
||||
unsigned char c = 0;
|
||||
Curl_rand(data, &c, 1);
|
||||
Curl_rand_bytes(data, FALSE, &c, 1);
|
||||
if(c >= ((100-ctx->wblock_percent)*256/100)) {
|
||||
CURL_TRC_CF(data, cf, "send(len=%zu) SIMULATE EWOULDBLOCK", orig_len);
|
||||
*err = CURLE_AGAIN;
|
||||
@@ -1597,6 +1619,18 @@ static ssize_t cf_socket_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
return nread;
|
||||
}
|
||||
|
||||
static void cf_socket_update_data(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
/* Update the IP info held in the transfer, if we have that. */
|
||||
if(cf->connected && (cf->sockindex == FIRSTSOCKET)) {
|
||||
struct cf_socket_ctx *ctx = cf->ctx;
|
||||
data->info.primary = ctx->ip;
|
||||
/* not sure if this is redundant... */
|
||||
data->info.conn_remote_port = cf->conn->remote_port;
|
||||
}
|
||||
}
|
||||
|
||||
static void cf_socket_active(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
{
|
||||
struct cf_socket_ctx *ctx = cf->ctx;
|
||||
@@ -1604,17 +1638,15 @@ static void cf_socket_active(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
/* use this socket from now on */
|
||||
cf->conn->sock[cf->sockindex] = ctx->sock;
|
||||
set_local_ip(cf, data);
|
||||
if(cf->sockindex == SECONDARYSOCKET)
|
||||
cf->conn->secondary = ctx->ip;
|
||||
else
|
||||
cf->conn->primary = ctx->ip;
|
||||
/* the first socket info gets some specials */
|
||||
if(cf->sockindex == FIRSTSOCKET) {
|
||||
cf->conn->primary = ctx->ip;
|
||||
cf->conn->remote_addr = &ctx->addr;
|
||||
#ifdef USE_IPV6
|
||||
cf->conn->bits.ipv6 = (ctx->addr.family == AF_INET6)? TRUE : FALSE;
|
||||
#endif
|
||||
Curl_persistconninfo(data, cf->conn, &ctx->ip);
|
||||
}
|
||||
else {
|
||||
cf->conn->secondary = ctx->ip;
|
||||
}
|
||||
ctx->active = TRUE;
|
||||
}
|
||||
@@ -1630,9 +1662,10 @@ static CURLcode cf_socket_cntrl(struct Curl_cfilter *cf,
|
||||
switch(event) {
|
||||
case CF_CTRL_CONN_INFO_UPDATE:
|
||||
cf_socket_active(cf, data);
|
||||
cf_socket_update_data(cf, data);
|
||||
break;
|
||||
case CF_CTRL_DATA_SETUP:
|
||||
Curl_persistconninfo(data, cf->conn, &ctx->ip);
|
||||
cf_socket_update_data(cf, data);
|
||||
break;
|
||||
case CF_CTRL_FORGET_SOCKET:
|
||||
ctx->sock = CURL_SOCKET_BAD;
|
||||
@@ -1715,6 +1748,14 @@ static CURLcode cf_socket_query(struct Curl_cfilter *cf,
|
||||
}
|
||||
return CURLE_OK;
|
||||
}
|
||||
case CF_QUERY_IP_INFO:
|
||||
#ifdef USE_IPV6
|
||||
*pres1 = (ctx->addr.family == AF_INET6)? TRUE : FALSE;
|
||||
#else
|
||||
*pres1 = FALSE;
|
||||
#endif
|
||||
*(struct ip_quadruple *)pres2 = ctx->ip;
|
||||
return CURLE_OK;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1793,7 +1834,7 @@ static CURLcode cf_udp_setup_quic(struct Curl_cfilter *cf,
|
||||
}
|
||||
ctx->sock_connected = TRUE;
|
||||
set_local_ip(cf, data);
|
||||
CURL_TRC_CF(data, cf, "%s socket %" CURL_FORMAT_SOCKET_T
|
||||
CURL_TRC_CF(data, cf, "%s socket %" FMT_SOCKET_T
|
||||
" connected: [%s:%d] -> [%s:%d]",
|
||||
(ctx->transport == TRNSPRT_QUIC)? "QUIC" : "UDP",
|
||||
ctx->sock, ctx->ip.local_ip, ctx->ip.local_port,
|
||||
@@ -1858,12 +1899,12 @@ static CURLcode cf_udp_connect(struct Curl_cfilter *cf,
|
||||
if(result)
|
||||
goto out;
|
||||
CURL_TRC_CF(data, cf, "cf_udp_connect(), opened socket=%"
|
||||
CURL_FORMAT_SOCKET_T " (%s:%d)",
|
||||
FMT_SOCKET_T " (%s:%d)",
|
||||
ctx->sock, ctx->ip.local_ip, ctx->ip.local_port);
|
||||
}
|
||||
else {
|
||||
CURL_TRC_CF(data, cf, "cf_udp_connect(), opened socket=%"
|
||||
CURL_FORMAT_SOCKET_T " (unconnected)", ctx->sock);
|
||||
FMT_SOCKET_T " (unconnected)", ctx->sock);
|
||||
}
|
||||
*done = TRUE;
|
||||
cf->connected = TRUE;
|
||||
@@ -2027,6 +2068,7 @@ CURLcode Curl_conn_tcp_listen_set(struct Curl_easy *data,
|
||||
}
|
||||
ctx->transport = conn->transport;
|
||||
ctx->sock = *s;
|
||||
ctx->listening = TRUE;
|
||||
ctx->accepted = FALSE;
|
||||
result = Curl_cf_create(&cf, &Curl_cft_tcp_accept, ctx);
|
||||
if(result)
|
||||
@@ -2038,8 +2080,8 @@ CURLcode Curl_conn_tcp_listen_set(struct Curl_easy *data,
|
||||
ctx->active = TRUE;
|
||||
ctx->connected_at = Curl_now();
|
||||
cf->connected = TRUE;
|
||||
CURL_TRC_CF(data, cf, "Curl_conn_tcp_listen_set(%"
|
||||
CURL_FORMAT_SOCKET_T ")", ctx->sock);
|
||||
CURL_TRC_CF(data, cf, "Curl_conn_tcp_listen_set(%" FMT_SOCKET_T ")",
|
||||
ctx->sock);
|
||||
|
||||
out:
|
||||
if(result) {
|
||||
@@ -2093,8 +2135,10 @@ CURLcode Curl_conn_tcp_accepted_set(struct Curl_easy *data,
|
||||
return CURLE_FAILED_INIT;
|
||||
|
||||
ctx = cf->ctx;
|
||||
DEBUGASSERT(ctx->listening);
|
||||
/* discard the listen socket */
|
||||
socket_close(data, conn, TRUE, ctx->sock);
|
||||
ctx->listening = FALSE;
|
||||
ctx->sock = *s;
|
||||
conn->sock[sockindex] = ctx->sock;
|
||||
set_accepted_remote_ip(cf, data);
|
||||
@@ -2103,7 +2147,7 @@ CURLcode Curl_conn_tcp_accepted_set(struct Curl_easy *data,
|
||||
ctx->accepted = TRUE;
|
||||
ctx->connected_at = Curl_now();
|
||||
cf->connected = TRUE;
|
||||
CURL_TRC_CF(data, cf, "accepted_set(sock=%" CURL_FORMAT_SOCKET_T
|
||||
CURL_TRC_CF(data, cf, "accepted_set(sock=%" FMT_SOCKET_T
|
||||
", remote=%s port=%d)",
|
||||
ctx->sock, ctx->ip.remote_ip, ctx->ip.remote_port);
|
||||
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@ struct Curl_sockaddr_ex {
|
||||
/*
|
||||
* Parse interface option, and return the interface name and the host part.
|
||||
*/
|
||||
CURLcode Curl_parse_interface(const char *input, size_t len,
|
||||
CURLcode Curl_parse_interface(const char *input,
|
||||
char **dev, char **iface, char **host);
|
||||
|
||||
/*
|
||||
|
||||
+64
-12
@@ -45,6 +45,9 @@
|
||||
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
|
||||
#endif
|
||||
|
||||
static void cf_cntrl_update_info(struct Curl_easy *data,
|
||||
struct connectdata *conn);
|
||||
|
||||
#ifdef UNITTESTS
|
||||
/* used by unit2600.c */
|
||||
void Curl_cf_def_close(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
@@ -98,10 +101,11 @@ bool Curl_cf_def_data_pending(struct Curl_cfilter *cf,
|
||||
}
|
||||
|
||||
ssize_t Curl_cf_def_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
const void *buf, size_t len, CURLcode *err)
|
||||
const void *buf, size_t len, bool eos,
|
||||
CURLcode *err)
|
||||
{
|
||||
return cf->next?
|
||||
cf->next->cft->do_send(cf->next, data, buf, len, err) :
|
||||
cf->next->cft->do_send(cf->next, data, buf, len, eos, err) :
|
||||
CURLE_RECV_ERROR;
|
||||
}
|
||||
|
||||
@@ -256,7 +260,8 @@ ssize_t Curl_cf_recv(struct Curl_easy *data, int num, char *buf,
|
||||
}
|
||||
|
||||
ssize_t Curl_cf_send(struct Curl_easy *data, int num,
|
||||
const void *mem, size_t len, CURLcode *code)
|
||||
const void *mem, size_t len, bool eos,
|
||||
CURLcode *code)
|
||||
{
|
||||
struct Curl_cfilter *cf;
|
||||
|
||||
@@ -268,7 +273,7 @@ ssize_t Curl_cf_send(struct Curl_easy *data, int num,
|
||||
cf = cf->next;
|
||||
}
|
||||
if(cf) {
|
||||
ssize_t nwritten = cf->cft->do_send(cf, data, mem, len, code);
|
||||
ssize_t nwritten = cf->cft->do_send(cf, data, mem, len, eos, code);
|
||||
DEBUGASSERT(nwritten >= 0 || *code);
|
||||
DEBUGASSERT(nwritten < 0 || !*code || !len);
|
||||
return nwritten;
|
||||
@@ -379,10 +384,11 @@ void Curl_conn_cf_close(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
}
|
||||
|
||||
ssize_t Curl_conn_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
const void *buf, size_t len, CURLcode *err)
|
||||
const void *buf, size_t len, bool eos,
|
||||
CURLcode *err)
|
||||
{
|
||||
if(cf)
|
||||
return cf->cft->do_send(cf, data, buf, len, err);
|
||||
return cf->cft->do_send(cf, data, buf, len, eos, err);
|
||||
*err = CURLE_SEND_ERROR;
|
||||
return -1;
|
||||
}
|
||||
@@ -416,11 +422,22 @@ CURLcode Curl_conn_connect(struct Curl_easy *data,
|
||||
|
||||
*done = cf->connected;
|
||||
if(!*done) {
|
||||
if(Curl_conn_needs_flush(data, sockindex)) {
|
||||
DEBUGF(infof(data, "Curl_conn_connect(index=%d), flush", sockindex));
|
||||
result = Curl_conn_flush(data, sockindex);
|
||||
if(result && (result != CURLE_AGAIN))
|
||||
return result;
|
||||
}
|
||||
|
||||
result = cf->cft->do_connect(cf, data, blocking, done);
|
||||
if(!result && *done) {
|
||||
Curl_conn_ev_update_info(data, data->conn);
|
||||
/* Now that the complete filter chain is connected, let all filters
|
||||
* persist information at the connection. E.g. cf-socket sets the
|
||||
* socket and ip related information. */
|
||||
cf_cntrl_update_info(data, data->conn);
|
||||
conn_report_connect_stats(data, data->conn);
|
||||
data->conn->keepalive = Curl_now();
|
||||
Curl_verboseconnect(data, data->conn, sockindex);
|
||||
}
|
||||
else if(result) {
|
||||
conn_report_connect_stats(data, data->conn);
|
||||
@@ -501,6 +518,21 @@ bool Curl_conn_data_pending(struct Curl_easy *data, int sockindex)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool Curl_conn_cf_needs_flush(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
CURLcode result;
|
||||
int pending = FALSE;
|
||||
result = cf? cf->cft->query(cf, data, CF_QUERY_NEED_FLUSH,
|
||||
&pending, NULL) : CURLE_UNKNOWN_OPTION;
|
||||
return (result || pending == FALSE)? FALSE : TRUE;
|
||||
}
|
||||
|
||||
bool Curl_conn_needs_flush(struct Curl_easy *data, int sockindex)
|
||||
{
|
||||
return Curl_conn_cf_needs_flush(data->conn->cfilter[sockindex], data);
|
||||
}
|
||||
|
||||
void Curl_conn_cf_adjust_pollset(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
struct easy_pollset *ps)
|
||||
@@ -627,6 +659,15 @@ curl_socket_t Curl_conn_cf_get_socket(struct Curl_cfilter *cf,
|
||||
return CURL_SOCKET_BAD;
|
||||
}
|
||||
|
||||
CURLcode Curl_conn_cf_get_ip_info(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
int *is_ipv6, struct ip_quadruple *ipquad)
|
||||
{
|
||||
if(cf)
|
||||
return cf->cft->query(cf, data, CF_QUERY_IP_INFO, is_ipv6, ipquad);
|
||||
return CURLE_UNKNOWN_OPTION;
|
||||
}
|
||||
|
||||
curl_socket_t Curl_conn_get_socket(struct Curl_easy *data, int sockindex)
|
||||
{
|
||||
struct Curl_cfilter *cf;
|
||||
@@ -693,6 +734,13 @@ CURLcode Curl_conn_ev_data_idle(struct Curl_easy *data)
|
||||
CF_CTRL_DATA_IDLE, 0, NULL);
|
||||
}
|
||||
|
||||
|
||||
CURLcode Curl_conn_flush(struct Curl_easy *data, int sockindex)
|
||||
{
|
||||
return Curl_conn_cf_cntrl(data->conn->cfilter[sockindex], data, FALSE,
|
||||
CF_CTRL_FLUSH, 0, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify connection filters that the transfer represented by `data`
|
||||
* is done with sending data (e.g. has uploaded everything).
|
||||
@@ -717,8 +765,8 @@ CURLcode Curl_conn_ev_data_pause(struct Curl_easy *data, bool do_pause)
|
||||
CF_CTRL_DATA_PAUSE, do_pause, NULL);
|
||||
}
|
||||
|
||||
void Curl_conn_ev_update_info(struct Curl_easy *data,
|
||||
struct connectdata *conn)
|
||||
static void cf_cntrl_update_info(struct Curl_easy *data,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
cf_cntrl_all(conn, data, TRUE, CF_CTRL_CONN_INFO_UPDATE, 0, NULL);
|
||||
}
|
||||
@@ -811,9 +859,10 @@ CURLcode Curl_conn_recv(struct Curl_easy *data, int sockindex,
|
||||
}
|
||||
|
||||
CURLcode Curl_conn_send(struct Curl_easy *data, int sockindex,
|
||||
const void *buf, size_t blen,
|
||||
const void *buf, size_t blen, bool eos,
|
||||
size_t *pnwritten)
|
||||
{
|
||||
size_t write_len = blen;
|
||||
ssize_t nwritten;
|
||||
CURLcode result = CURLE_OK;
|
||||
struct connectdata *conn;
|
||||
@@ -831,11 +880,14 @@ CURLcode Curl_conn_send(struct Curl_easy *data, int sockindex,
|
||||
if(p) {
|
||||
size_t altsize = (size_t)strtoul(p, NULL, 10);
|
||||
if(altsize)
|
||||
blen = CURLMIN(blen, altsize);
|
||||
write_len = CURLMIN(write_len, altsize);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
nwritten = conn->send[sockindex](data, sockindex, buf, blen, &result);
|
||||
if(write_len != blen)
|
||||
eos = FALSE;
|
||||
nwritten = conn->send[sockindex](data, sockindex, buf, write_len, eos,
|
||||
&result);
|
||||
DEBUGASSERT((nwritten >= 0) || result);
|
||||
*pnwritten = (nwritten < 0)? 0 : (size_t)nwritten;
|
||||
return result;
|
||||
|
||||
+31
-10
@@ -30,6 +30,7 @@ struct Curl_cfilter;
|
||||
struct Curl_easy;
|
||||
struct Curl_dns_entry;
|
||||
struct connectdata;
|
||||
struct ip_quadruple;
|
||||
|
||||
/* Callback to destroy resources held by this filter instance.
|
||||
* Implementations MUST NOT chain calls to cf->next.
|
||||
@@ -105,6 +106,7 @@ typedef ssize_t Curl_cft_send(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data, /* transfer */
|
||||
const void *buf, /* data to write */
|
||||
size_t len, /* amount to write */
|
||||
bool eos, /* last chunk */
|
||||
CURLcode *err); /* error to return */
|
||||
|
||||
typedef ssize_t Curl_cft_recv(struct Curl_cfilter *cf,
|
||||
@@ -140,6 +142,7 @@ typedef CURLcode Curl_cft_conn_keep_alive(struct Curl_cfilter *cf,
|
||||
/* update conn info at connection and data */
|
||||
#define CF_CTRL_CONN_INFO_UPDATE (256+0) /* 0 NULL ignored */
|
||||
#define CF_CTRL_FORGET_SOCKET (256+1) /* 0 NULL ignored */
|
||||
#define CF_CTRL_FLUSH (256+2) /* 0 NULL first fail */
|
||||
|
||||
/**
|
||||
* Handle event/control for the filter.
|
||||
@@ -162,6 +165,9 @@ typedef CURLcode Curl_cft_cntrl(struct Curl_cfilter *cf,
|
||||
* were received.
|
||||
* -1 if not determined yet.
|
||||
* - CF_QUERY_SOCKET: the socket used by the filter chain
|
||||
* - CF_QUERY_NEED_FLUSH: TRUE iff any of the filters have unsent data
|
||||
* - CF_QUERY_IP_INFO: res1 says if connection used IPv6, res2 is the
|
||||
* ip quadruple
|
||||
*/
|
||||
/* query res1 res2 */
|
||||
#define CF_QUERY_MAX_CONCURRENT 1 /* number - */
|
||||
@@ -170,6 +176,8 @@ typedef CURLcode Curl_cft_cntrl(struct Curl_cfilter *cf,
|
||||
#define CF_QUERY_TIMER_CONNECT 4 /* - struct curltime */
|
||||
#define CF_QUERY_TIMER_APPCONNECT 5 /* - struct curltime */
|
||||
#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 */
|
||||
|
||||
/**
|
||||
* Query the cfilter for properties. Filters ignorant of a query will
|
||||
@@ -241,7 +249,8 @@ void Curl_cf_def_adjust_pollset(struct Curl_cfilter *cf,
|
||||
bool Curl_cf_def_data_pending(struct Curl_cfilter *cf,
|
||||
const struct Curl_easy *data);
|
||||
ssize_t Curl_cf_def_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
const void *buf, size_t len, CURLcode *err);
|
||||
const void *buf, size_t len, bool eos,
|
||||
CURLcode *err);
|
||||
ssize_t Curl_cf_def_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
char *buf, size_t len, CURLcode *err);
|
||||
CURLcode Curl_cf_def_cntrl(struct Curl_cfilter *cf,
|
||||
@@ -317,7 +326,8 @@ CURLcode Curl_conn_cf_connect(struct Curl_cfilter *cf,
|
||||
bool blocking, bool *done);
|
||||
void Curl_conn_cf_close(struct Curl_cfilter *cf, struct Curl_easy *data);
|
||||
ssize_t Curl_conn_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
const void *buf, size_t len, CURLcode *err);
|
||||
const void *buf, size_t len, bool eos,
|
||||
CURLcode *err);
|
||||
ssize_t Curl_conn_cf_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
char *buf, size_t len, CURLcode *err);
|
||||
CURLcode Curl_conn_cf_cntrl(struct Curl_cfilter *cf,
|
||||
@@ -338,6 +348,12 @@ bool Curl_conn_cf_is_ssl(struct Curl_cfilter *cf);
|
||||
curl_socket_t Curl_conn_cf_get_socket(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data);
|
||||
|
||||
CURLcode Curl_conn_cf_get_ip_info(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
int *is_ipv6, struct ip_quadruple *ipquad);
|
||||
|
||||
bool Curl_conn_cf_needs_flush(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data);
|
||||
|
||||
#define CURL_CF_SSL_DEFAULT -1
|
||||
#define CURL_CF_SSL_DISABLE 0
|
||||
@@ -398,6 +414,17 @@ CURLcode Curl_conn_shutdown(struct Curl_easy *data, int sockindex, bool *done);
|
||||
bool Curl_conn_data_pending(struct Curl_easy *data,
|
||||
int sockindex);
|
||||
|
||||
/**
|
||||
* Return TRUE if any of the connection filters at chain `sockindex`
|
||||
* have data still to send.
|
||||
*/
|
||||
bool Curl_conn_needs_flush(struct Curl_easy *data, int sockindex);
|
||||
|
||||
/**
|
||||
* Flush any pending data on the connection filters at chain `sockindex`.
|
||||
*/
|
||||
CURLcode Curl_conn_flush(struct Curl_easy *data, int sockindex);
|
||||
|
||||
/**
|
||||
* Return the socket used on data's connection for the index.
|
||||
* Returns CURL_SOCKET_BAD if not available.
|
||||
@@ -447,7 +474,7 @@ ssize_t Curl_cf_recv(struct Curl_easy *data, int sockindex, char *buf,
|
||||
* The error code is placed into `*code`.
|
||||
*/
|
||||
ssize_t Curl_cf_send(struct Curl_easy *data, int sockindex,
|
||||
const void *buf, size_t len, CURLcode *code);
|
||||
const void *buf, size_t len, bool eos, CURLcode *code);
|
||||
|
||||
/**
|
||||
* The easy handle `data` is being attached to `conn`. This does
|
||||
@@ -496,12 +523,6 @@ void Curl_conn_ev_data_done(struct Curl_easy *data, bool premature);
|
||||
*/
|
||||
CURLcode Curl_conn_ev_data_pause(struct Curl_easy *data, bool do_pause);
|
||||
|
||||
/**
|
||||
* Inform connection filters to update their info in `conn`.
|
||||
*/
|
||||
void Curl_conn_ev_update_info(struct Curl_easy *data,
|
||||
struct connectdata *conn);
|
||||
|
||||
/**
|
||||
* Check if FIRSTSOCKET's cfilter chain deems connection alive.
|
||||
*/
|
||||
@@ -557,7 +578,7 @@ CURLcode Curl_conn_recv(struct Curl_easy *data, int sockindex,
|
||||
* Will return CURLE_AGAIN iff blocked on sending.
|
||||
*/
|
||||
CURLcode Curl_conn_send(struct Curl_easy *data, int sockindex,
|
||||
const void *buf, size_t blen,
|
||||
const void *buf, size_t blen, bool eos,
|
||||
size_t *pnwritten);
|
||||
|
||||
|
||||
|
||||
+748
-555
@@ -47,194 +47,242 @@
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
#define HASHKEY_SIZE 128
|
||||
|
||||
static void connc_discard_conn(struct conncache *connc,
|
||||
struct Curl_easy *last_data,
|
||||
#define CPOOL_IS_LOCKED(c) ((c) && (c)->locked)
|
||||
|
||||
#define CPOOL_LOCK(c) \
|
||||
do { \
|
||||
if((c)) { \
|
||||
if(CURL_SHARE_KEEP_CONNECT((c)->share)) \
|
||||
Curl_share_lock(((c)->idata), CURL_LOCK_DATA_CONNECT, \
|
||||
CURL_LOCK_ACCESS_SINGLE); \
|
||||
DEBUGASSERT(!(c)->locked); \
|
||||
(c)->locked = TRUE; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define CPOOL_UNLOCK(c) \
|
||||
do { \
|
||||
if((c)) { \
|
||||
DEBUGASSERT((c)->locked); \
|
||||
(c)->locked = FALSE; \
|
||||
if(CURL_SHARE_KEEP_CONNECT((c)->share)) \
|
||||
Curl_share_unlock((c)->idata, CURL_LOCK_DATA_CONNECT); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
|
||||
/* A list of connections to the same destinationn. */
|
||||
struct cpool_bundle {
|
||||
struct Curl_llist conns; /* connections in the bundle */
|
||||
size_t dest_len; /* total length of destination, including NUL */
|
||||
char *dest[1]; /* destination of bundle, allocated to keep dest_len bytes */
|
||||
};
|
||||
|
||||
|
||||
static void cpool_discard_conn(struct cpool *cpool,
|
||||
struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
bool aborted);
|
||||
static void connc_disconnect(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
struct conncache *connc,
|
||||
bool do_shutdown);
|
||||
static void connc_run_conn_shutdown(struct Curl_easy *data,
|
||||
static void cpool_close_and_destroy(struct cpool *cpool,
|
||||
struct connectdata *conn,
|
||||
struct Curl_easy *data,
|
||||
bool do_shutdown);
|
||||
static void cpool_run_conn_shutdown(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
bool *done);
|
||||
static void connc_run_conn_shutdown_handler(struct Curl_easy *data,
|
||||
static void cpool_run_conn_shutdown_handler(struct Curl_easy *data,
|
||||
struct connectdata *conn);
|
||||
static CURLMcode connc_update_shutdown_ev(struct Curl_multi *multi,
|
||||
static CURLMcode cpool_update_shutdown_ev(struct Curl_multi *multi,
|
||||
struct Curl_easy *data,
|
||||
struct connectdata *conn);
|
||||
static void connc_shutdown_all(struct conncache *connc, int timeout_ms);
|
||||
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 CURLcode bundle_create(struct connectbundle **bundlep)
|
||||
static struct cpool_bundle *cpool_bundle_create(const char *dest,
|
||||
size_t dest_len)
|
||||
{
|
||||
DEBUGASSERT(*bundlep == NULL);
|
||||
*bundlep = malloc(sizeof(struct connectbundle));
|
||||
if(!*bundlep)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
(*bundlep)->num_connections = 0;
|
||||
(*bundlep)->multiuse = BUNDLE_UNKNOWN;
|
||||
|
||||
Curl_llist_init(&(*bundlep)->conn_list, NULL);
|
||||
return CURLE_OK;
|
||||
struct cpool_bundle *bundle;
|
||||
bundle = calloc(1, sizeof(*bundle) + dest_len);
|
||||
if(!bundle)
|
||||
return NULL;
|
||||
Curl_llist_init(&bundle->conns, NULL);
|
||||
bundle->dest_len = dest_len;
|
||||
memcpy(bundle->dest, dest, dest_len);
|
||||
return bundle;
|
||||
}
|
||||
|
||||
static void bundle_destroy(struct connectbundle *bundle)
|
||||
static void cpool_bundle_destroy(struct cpool_bundle *bundle)
|
||||
{
|
||||
DEBUGASSERT(!Curl_llist_count(&bundle->conns));
|
||||
free(bundle);
|
||||
}
|
||||
|
||||
/* Add a connection to a bundle */
|
||||
static void bundle_add_conn(struct connectbundle *bundle,
|
||||
struct connectdata *conn)
|
||||
static void cpool_bundle_add(struct cpool_bundle *bundle,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
Curl_llist_append(&bundle->conn_list, conn, &conn->bundle_node);
|
||||
conn->bundle = bundle;
|
||||
bundle->num_connections++;
|
||||
DEBUGASSERT(!Curl_node_llist(&conn->cpool_node));
|
||||
Curl_llist_append(&bundle->conns, conn, &conn->cpool_node);
|
||||
conn->bits.in_cpool = TRUE;
|
||||
}
|
||||
|
||||
/* Remove a connection from a bundle */
|
||||
static int bundle_remove_conn(struct connectbundle *bundle,
|
||||
struct connectdata *conn)
|
||||
static void cpool_bundle_remove(struct cpool_bundle *bundle,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
struct Curl_llist_element *curr;
|
||||
|
||||
curr = bundle->conn_list.head;
|
||||
while(curr) {
|
||||
if(curr->ptr == conn) {
|
||||
Curl_llist_remove(&bundle->conn_list, curr, NULL);
|
||||
bundle->num_connections--;
|
||||
conn->bundle = NULL;
|
||||
return 1; /* we removed a handle */
|
||||
}
|
||||
curr = curr->next;
|
||||
}
|
||||
DEBUGASSERT(0);
|
||||
return 0;
|
||||
(void)bundle;
|
||||
DEBUGASSERT(Curl_node_llist(&conn->cpool_node) == &bundle->conns);
|
||||
Curl_node_remove(&conn->cpool_node);
|
||||
conn->bits.in_cpool = FALSE;
|
||||
}
|
||||
|
||||
static void free_bundle_hash_entry(void *freethis)
|
||||
static void cpool_bundle_free_entry(void *freethis)
|
||||
{
|
||||
struct connectbundle *b = (struct connectbundle *) freethis;
|
||||
|
||||
bundle_destroy(b);
|
||||
cpool_bundle_destroy((struct cpool_bundle *)freethis);
|
||||
}
|
||||
|
||||
int Curl_conncache_init(struct conncache *connc,
|
||||
struct Curl_multi *multi, size_t size)
|
||||
int Curl_cpool_init(struct cpool *cpool,
|
||||
Curl_cpool_disconnect_cb *disconnect_cb,
|
||||
struct Curl_multi *multi,
|
||||
struct Curl_share *share,
|
||||
size_t size)
|
||||
{
|
||||
DEBUGASSERT(!!multi != !!share); /* either one */
|
||||
Curl_hash_init(&cpool->dest2bundle, size, Curl_hash_str,
|
||||
Curl_str_key_compare, cpool_bundle_free_entry);
|
||||
Curl_llist_init(&cpool->shutdowns, NULL);
|
||||
|
||||
DEBUGASSERT(disconnect_cb);
|
||||
if(!disconnect_cb)
|
||||
return 1;
|
||||
|
||||
/* allocate a new easy handle to use when closing cached connections */
|
||||
connc->closure_handle = curl_easy_init();
|
||||
if(!connc->closure_handle)
|
||||
cpool->idata = curl_easy_init();
|
||||
if(!cpool->idata)
|
||||
return 1; /* bad */
|
||||
connc->closure_handle->state.internal = true;
|
||||
cpool->idata->state.internal = true;
|
||||
/* TODO: this is quirky. We need an internal handle for certain
|
||||
* operations, but we do not add it to the multi (if there is one).
|
||||
* But we give it the multi so that socket event operations can work.
|
||||
* Probably better to have an internal handle owned by the multi that
|
||||
* can be used for cpool operations. */
|
||||
cpool->idata->multi = multi;
|
||||
#ifdef DEBUGBUILD
|
||||
if(getenv("CURL_DEBUG"))
|
||||
connc->closure_handle->set.verbose = true;
|
||||
cpool->idata->set.verbose = true;
|
||||
#endif
|
||||
|
||||
Curl_hash_init(&connc->hash, size, Curl_hash_str,
|
||||
Curl_str_key_compare, free_bundle_hash_entry);
|
||||
connc->closure_handle->state.conn_cache = connc;
|
||||
connc->multi = multi;
|
||||
Curl_llist_init(&connc->shutdowns.conn_list, NULL);
|
||||
cpool->disconnect_cb = disconnect_cb;
|
||||
cpool->idata->multi = cpool->multi = multi;
|
||||
cpool->idata->share = cpool->share = share;
|
||||
|
||||
return 0; /* good */
|
||||
}
|
||||
|
||||
void Curl_conncache_destroy(struct conncache *connc)
|
||||
void Curl_cpool_destroy(struct cpool *cpool)
|
||||
{
|
||||
if(connc) {
|
||||
Curl_hash_destroy(&connc->hash);
|
||||
connc->multi = NULL;
|
||||
DEBUGASSERT(!Curl_llist_count(&connc->shutdowns.conn_list));
|
||||
if(cpool) {
|
||||
if(cpool->idata) {
|
||||
cpool_close_and_destroy_all(cpool);
|
||||
/* The internal closure handle is special and we need to
|
||||
* disconnect it from multi/share before closing it down. */
|
||||
cpool->idata->multi = NULL;
|
||||
cpool->idata->share = NULL;
|
||||
Curl_close(&cpool->idata);
|
||||
}
|
||||
Curl_hash_destroy(&cpool->dest2bundle);
|
||||
cpool->multi = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* creates a key to find a bundle for this connection */
|
||||
static void hashkey(struct connectdata *conn, char *buf, size_t len)
|
||||
static struct cpool *cpool_get_instance(struct Curl_easy *data)
|
||||
{
|
||||
const char *hostname;
|
||||
long port = conn->remote_port;
|
||||
DEBUGASSERT(len >= HASHKEY_SIZE);
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
|
||||
hostname = conn->http_proxy.host.name;
|
||||
port = conn->primary.remote_port;
|
||||
if(data) {
|
||||
if(CURL_SHARE_KEEP_CONNECT(data->share))
|
||||
return &data->share->cpool;
|
||||
else if(data->multi_easy)
|
||||
return &data->multi_easy->cpool;
|
||||
else if(data->multi)
|
||||
return &data->multi->cpool;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if(conn->bits.conn_to_host)
|
||||
hostname = conn->conn_to_host.name;
|
||||
else
|
||||
hostname = conn->host.name;
|
||||
|
||||
/* put the numbers first so that the hostname gets cut off if too long */
|
||||
#ifdef USE_IPV6
|
||||
msnprintf(buf, len, "%u/%ld/%s", conn->scope_id, port, hostname);
|
||||
#else
|
||||
msnprintf(buf, len, "%ld/%s", port, hostname);
|
||||
#endif
|
||||
Curl_strntolower(buf, buf, len);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Returns number of connections currently held in the connection cache.
|
||||
Locks/unlocks the cache itself!
|
||||
*/
|
||||
size_t Curl_conncache_size(struct Curl_easy *data)
|
||||
void Curl_cpool_xfer_init(struct Curl_easy *data)
|
||||
{
|
||||
size_t num;
|
||||
CONNCACHE_LOCK(data);
|
||||
num = data->state.conn_cache->num_conn;
|
||||
CONNCACHE_UNLOCK(data);
|
||||
return num;
|
||||
struct cpool *cpool = cpool_get_instance(data);
|
||||
|
||||
DEBUGASSERT(cpool);
|
||||
if(cpool) {
|
||||
CPOOL_LOCK(cpool);
|
||||
/* the identifier inside the connection cache */
|
||||
data->id = cpool->next_easy_id++;
|
||||
if(cpool->next_easy_id <= 0)
|
||||
cpool->next_easy_id = 0;
|
||||
data->state.lastconnect_id = -1;
|
||||
|
||||
/* The closure handle only ever has default timeouts set. To improve the
|
||||
state somewhat we clone the timeouts from each added handle so that the
|
||||
closure handle always has the same timeouts as the most recently added
|
||||
easy handle. */
|
||||
cpool->idata->set.timeout = data->set.timeout;
|
||||
cpool->idata->set.server_response_timeout =
|
||||
data->set.server_response_timeout;
|
||||
cpool->idata->set.no_signal = data->set.no_signal;
|
||||
|
||||
CPOOL_UNLOCK(cpool);
|
||||
}
|
||||
else {
|
||||
/* We should not get here, but in a non-debug build, do something */
|
||||
data->id = 0;
|
||||
data->state.lastconnect_id = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Look up the bundle with all the connections to the same host this
|
||||
connectdata struct is setup to use.
|
||||
|
||||
**NOTE**: When it returns, it holds the connection cache lock! */
|
||||
struct connectbundle *
|
||||
Curl_conncache_find_bundle(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
struct conncache *connc)
|
||||
static struct cpool_bundle *cpool_find_bundle(struct cpool *cpool,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
struct connectbundle *bundle = NULL;
|
||||
CONNCACHE_LOCK(data);
|
||||
if(connc) {
|
||||
char key[HASHKEY_SIZE];
|
||||
hashkey(conn, key, sizeof(key));
|
||||
bundle = Curl_hash_pick(&connc->hash, key, strlen(key));
|
||||
}
|
||||
return Curl_hash_pick(&cpool->dest2bundle,
|
||||
conn->destination, conn->destination_len);
|
||||
}
|
||||
|
||||
static struct cpool_bundle *
|
||||
cpool_add_bundle(struct cpool *cpool, struct connectdata *conn)
|
||||
{
|
||||
struct cpool_bundle *bundle;
|
||||
|
||||
bundle = cpool_bundle_create(conn->destination, conn->destination_len);
|
||||
if(!bundle)
|
||||
return NULL;
|
||||
|
||||
if(!Curl_hash_add(&cpool->dest2bundle,
|
||||
bundle->dest, bundle->dest_len, bundle)) {
|
||||
cpool_bundle_destroy(bundle);
|
||||
return NULL;
|
||||
}
|
||||
return bundle;
|
||||
}
|
||||
|
||||
static void *connc_add_bundle(struct conncache *connc,
|
||||
char *key, struct connectbundle *bundle)
|
||||
{
|
||||
return Curl_hash_add(&connc->hash, key, strlen(key), bundle);
|
||||
}
|
||||
|
||||
static void connc_remove_bundle(struct conncache *connc,
|
||||
struct connectbundle *bundle)
|
||||
static void cpool_remove_bundle(struct cpool *cpool,
|
||||
struct cpool_bundle *bundle)
|
||||
{
|
||||
struct Curl_hash_iterator iter;
|
||||
struct Curl_hash_element *he;
|
||||
|
||||
if(!connc)
|
||||
if(!cpool)
|
||||
return;
|
||||
|
||||
Curl_hash_start_iterate(&connc->hash, &iter);
|
||||
Curl_hash_start_iterate(&cpool->dest2bundle, &iter);
|
||||
|
||||
he = Curl_hash_next_element(&iter);
|
||||
while(he) {
|
||||
if(he->ptr == bundle) {
|
||||
/* The bundle is destroyed by the hash destructor function,
|
||||
free_bundle_hash_entry() */
|
||||
Curl_hash_delete(&connc->hash, he->key, he->key_len);
|
||||
Curl_hash_delete(&cpool->dest2bundle, he->key, he->key_len);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -242,229 +290,252 @@ static void connc_remove_bundle(struct conncache *connc,
|
||||
}
|
||||
}
|
||||
|
||||
CURLcode Curl_conncache_add_conn(struct Curl_easy *data)
|
||||
static struct connectdata *
|
||||
cpool_bundle_get_oldest_idle(struct cpool_bundle *bundle);
|
||||
|
||||
int Curl_cpool_check_limits(struct Curl_easy *data,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct connectbundle *bundle = NULL;
|
||||
struct connectdata *conn = data->conn;
|
||||
struct conncache *connc = data->state.conn_cache;
|
||||
DEBUGASSERT(conn);
|
||||
struct cpool *cpool = cpool_get_instance(data);
|
||||
struct cpool_bundle *bundle;
|
||||
size_t dest_limit = 0;
|
||||
size_t total_limit = 0;
|
||||
int result = CPOOL_LIMIT_OK;
|
||||
|
||||
/* *find_bundle() locks the connection cache */
|
||||
bundle = Curl_conncache_find_bundle(data, conn, data->state.conn_cache);
|
||||
if(!bundle) {
|
||||
char key[HASHKEY_SIZE];
|
||||
if(!cpool)
|
||||
return CPOOL_LIMIT_OK;
|
||||
|
||||
result = bundle_create(&bundle);
|
||||
if(result) {
|
||||
goto unlock;
|
||||
if(data && data->multi) {
|
||||
dest_limit = data->multi->max_host_connections;
|
||||
total_limit = data->multi->max_total_connections;
|
||||
}
|
||||
|
||||
if(!dest_limit && !total_limit)
|
||||
return CPOOL_LIMIT_OK;
|
||||
|
||||
CPOOL_LOCK(cpool);
|
||||
if(dest_limit) {
|
||||
bundle = cpool_find_bundle(cpool, conn);
|
||||
while(bundle && (Curl_llist_count(&bundle->conns) >= dest_limit)) {
|
||||
struct connectdata *oldest_idle = NULL;
|
||||
/* The bundle is full. Extract the oldest connection that may
|
||||
* be removed now, if there is one. */
|
||||
oldest_idle = cpool_bundle_get_oldest_idle(bundle);
|
||||
if(!oldest_idle)
|
||||
break;
|
||||
/* disconnect the old conn and continue */
|
||||
DEBUGF(infof(data, "Discarding connection #%"
|
||||
FMT_OFF_T " from %zu to reach destination "
|
||||
"limit of %zu", oldest_idle->connection_id,
|
||||
Curl_llist_count(&bundle->conns), dest_limit));
|
||||
Curl_cpool_disconnect(data, oldest_idle, FALSE);
|
||||
}
|
||||
|
||||
hashkey(conn, key, sizeof(key));
|
||||
|
||||
if(!connc_add_bundle(data->state.conn_cache, key, bundle)) {
|
||||
bundle_destroy(bundle);
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto unlock;
|
||||
if(bundle && (Curl_llist_count(&bundle->conns) >= dest_limit)) {
|
||||
result = CPOOL_LIMIT_DEST;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
bundle_add_conn(bundle, conn);
|
||||
conn->connection_id = connc->next_connection_id++;
|
||||
connc->num_conn++;
|
||||
if(total_limit) {
|
||||
while(cpool->num_conn >= total_limit) {
|
||||
struct connectdata *oldest_idle = cpool_get_oldest_idle(cpool);
|
||||
if(!oldest_idle)
|
||||
break;
|
||||
/* disconnect the old conn and continue */
|
||||
DEBUGF(infof(data, "Discarding connection #%"
|
||||
FMT_OFF_T " from %zu to reach total "
|
||||
"limit of %zu",
|
||||
oldest_idle->connection_id, cpool->num_conn, total_limit));
|
||||
Curl_cpool_disconnect(data, oldest_idle, FALSE);
|
||||
}
|
||||
if(cpool->num_conn >= total_limit) {
|
||||
result = CPOOL_LIMIT_TOTAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUGF(infof(data, "Added connection %" CURL_FORMAT_CURL_OFF_T ". "
|
||||
out:
|
||||
CPOOL_UNLOCK(cpool);
|
||||
return result;
|
||||
}
|
||||
|
||||
CURLcode Curl_cpool_add_conn(struct Curl_easy *data,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct cpool_bundle *bundle = NULL;
|
||||
struct cpool *cpool = cpool_get_instance(data);
|
||||
DEBUGASSERT(conn);
|
||||
|
||||
DEBUGASSERT(cpool);
|
||||
if(!cpool)
|
||||
return CURLE_FAILED_INIT;
|
||||
|
||||
CPOOL_LOCK(cpool);
|
||||
bundle = cpool_find_bundle(cpool, conn);
|
||||
if(!bundle) {
|
||||
bundle = cpool_add_bundle(cpool, conn);
|
||||
if(!bundle) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
cpool_bundle_add(bundle, conn);
|
||||
conn->connection_id = cpool->next_connection_id++;
|
||||
cpool->num_conn++;
|
||||
DEBUGF(infof(data, "Added connection %" FMT_OFF_T ". "
|
||||
"The cache now contains %zu members",
|
||||
conn->connection_id, connc->num_conn));
|
||||
|
||||
unlock:
|
||||
CONNCACHE_UNLOCK(data);
|
||||
conn->connection_id, cpool->num_conn));
|
||||
out:
|
||||
CPOOL_UNLOCK(cpool);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void connc_remove_conn(struct conncache *connc,
|
||||
static void cpool_remove_conn(struct cpool *cpool,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
struct connectbundle *bundle = conn->bundle;
|
||||
|
||||
/* The bundle pointer can be NULL, since this function can be called
|
||||
due to a failed connection attempt, before being added to a bundle */
|
||||
if(bundle) {
|
||||
bundle_remove_conn(bundle, conn);
|
||||
if(connc && bundle->num_connections == 0)
|
||||
connc_remove_bundle(connc, bundle);
|
||||
conn->bundle = NULL; /* removed from it */
|
||||
if(connc)
|
||||
connc->num_conn--;
|
||||
struct Curl_llist *list = Curl_node_llist(&conn->cpool_node);
|
||||
DEBUGASSERT(cpool);
|
||||
if(list) {
|
||||
/* The connection is certainly in the pool, but where? */
|
||||
struct cpool_bundle *bundle = cpool_find_bundle(cpool, conn);
|
||||
if(bundle && (list == &bundle->conns)) {
|
||||
cpool_bundle_remove(bundle, conn);
|
||||
if(!Curl_llist_count(&bundle->conns))
|
||||
cpool_remove_bundle(cpool, bundle);
|
||||
conn->bits.in_cpool = FALSE;
|
||||
cpool->num_conn--;
|
||||
}
|
||||
else {
|
||||
/* Not in a bundle, already in the shutdown list? */
|
||||
DEBUGASSERT(list == &cpool->shutdowns);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Removes the connectdata object from the connection cache, but the transfer
|
||||
* still owns this connection.
|
||||
*
|
||||
* Pass TRUE/FALSE in the 'lock' argument depending on if the parent function
|
||||
* already holds the lock or not.
|
||||
*/
|
||||
void Curl_conncache_remove_conn(struct Curl_easy *data,
|
||||
struct connectdata *conn, bool lock)
|
||||
{
|
||||
struct conncache *connc = data->state.conn_cache;
|
||||
|
||||
if(lock)
|
||||
CONNCACHE_LOCK(data);
|
||||
connc_remove_conn(connc, conn);
|
||||
if(lock)
|
||||
CONNCACHE_UNLOCK(data);
|
||||
if(connc)
|
||||
DEBUGF(infof(data, "The cache now contains %zu members",
|
||||
connc->num_conn));
|
||||
}
|
||||
|
||||
/* This function iterates the entire connection cache and calls the function
|
||||
/* This function iterates the entire connection pool and calls the function
|
||||
func() with the connection pointer as the first argument and the supplied
|
||||
'param' argument as the other.
|
||||
|
||||
The conncache lock is still held when the callback is called. It needs it,
|
||||
The cpool lock is still held when the callback is called. It needs it,
|
||||
so that it can safely continue traversing the lists once the callback
|
||||
returns.
|
||||
|
||||
Returns 1 if the loop was aborted due to the callback's return code.
|
||||
Returns TRUE if the loop was aborted due to the callback's return code.
|
||||
|
||||
Return 0 from func() to continue the loop, return 1 to abort it.
|
||||
*/
|
||||
bool Curl_conncache_foreach(struct Curl_easy *data,
|
||||
struct conncache *connc,
|
||||
void *param,
|
||||
int (*func)(struct Curl_easy *data,
|
||||
struct connectdata *conn, void *param))
|
||||
static bool cpool_foreach(struct Curl_easy *data,
|
||||
struct cpool *cpool,
|
||||
void *param,
|
||||
int (*func)(struct Curl_easy *data,
|
||||
struct connectdata *conn, void *param))
|
||||
{
|
||||
struct Curl_hash_iterator iter;
|
||||
struct Curl_llist_element *curr;
|
||||
struct Curl_hash_element *he;
|
||||
|
||||
if(!connc)
|
||||
if(!cpool)
|
||||
return FALSE;
|
||||
|
||||
CONNCACHE_LOCK(data);
|
||||
Curl_hash_start_iterate(&connc->hash, &iter);
|
||||
Curl_hash_start_iterate(&cpool->dest2bundle, &iter);
|
||||
|
||||
he = Curl_hash_next_element(&iter);
|
||||
while(he) {
|
||||
struct connectbundle *bundle;
|
||||
|
||||
bundle = he->ptr;
|
||||
struct Curl_llist_node *curr;
|
||||
struct cpool_bundle *bundle = he->ptr;
|
||||
he = Curl_hash_next_element(&iter);
|
||||
|
||||
curr = bundle->conn_list.head;
|
||||
curr = Curl_llist_head(&bundle->conns);
|
||||
while(curr) {
|
||||
/* Yes, we need to update curr before calling func(), because func()
|
||||
might decide to remove the connection */
|
||||
struct connectdata *conn = curr->ptr;
|
||||
curr = curr->next;
|
||||
struct connectdata *conn = Curl_node_elem(curr);
|
||||
curr = Curl_node_next(curr);
|
||||
|
||||
if(1 == func(data, conn, param)) {
|
||||
CONNCACHE_UNLOCK(data);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
CONNCACHE_UNLOCK(data);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Return the first connection found in the cache. Used when closing all
|
||||
connections.
|
||||
|
||||
NOTE: no locking is done here as this is presumably only done when cleaning
|
||||
up a cache!
|
||||
*/
|
||||
static struct connectdata *
|
||||
connc_find_first_connection(struct conncache *connc)
|
||||
/* Return a live connection in the pool or NULL. */
|
||||
static struct connectdata *cpool_get_live_conn(struct cpool *cpool)
|
||||
{
|
||||
struct Curl_hash_iterator iter;
|
||||
struct Curl_hash_element *he;
|
||||
struct connectbundle *bundle;
|
||||
struct cpool_bundle *bundle;
|
||||
struct Curl_llist_node *conn_node;
|
||||
|
||||
Curl_hash_start_iterate(&connc->hash, &iter);
|
||||
|
||||
he = Curl_hash_next_element(&iter);
|
||||
while(he) {
|
||||
struct Curl_llist_element *curr;
|
||||
Curl_hash_start_iterate(&cpool->dest2bundle, &iter);
|
||||
for(he = Curl_hash_next_element(&iter); he;
|
||||
he = Curl_hash_next_element(&iter)) {
|
||||
bundle = he->ptr;
|
||||
|
||||
curr = bundle->conn_list.head;
|
||||
if(curr) {
|
||||
return curr->ptr;
|
||||
}
|
||||
|
||||
he = Curl_hash_next_element(&iter);
|
||||
conn_node = Curl_llist_head(&bundle->conns);
|
||||
if(conn_node)
|
||||
return Curl_node_elem(conn_node);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Give ownership of a connection back to the connection cache. Might
|
||||
* disconnect the oldest existing in there to make space.
|
||||
* A connection (already in the pool) has become idle. Do any
|
||||
* cleanups in regard to the pool's limits.
|
||||
*
|
||||
* Return TRUE if stored, FALSE if closed.
|
||||
* Return TRUE if idle connection kept in pool, FALSE if closed.
|
||||
*/
|
||||
bool Curl_conncache_return_conn(struct Curl_easy *data,
|
||||
struct connectdata *conn)
|
||||
bool Curl_cpool_conn_now_idle(struct Curl_easy *data,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
unsigned int maxconnects = !data->multi->maxconnects ?
|
||||
data->multi->num_easy * 4: data->multi->maxconnects;
|
||||
struct connectdata *conn_candidate = NULL;
|
||||
struct connectdata *oldest_idle = NULL;
|
||||
struct cpool *cpool = cpool_get_instance(data);
|
||||
bool kept = TRUE;
|
||||
|
||||
conn->lastused = Curl_now(); /* it was used up until now */
|
||||
if(maxconnects && Curl_conncache_size(data) > maxconnects) {
|
||||
infof(data, "Connection cache is full, closing the oldest one");
|
||||
if(cpool && maxconnects) {
|
||||
/* may be called form a callback already under lock */
|
||||
bool do_lock = !CPOOL_IS_LOCKED(cpool);
|
||||
if(do_lock)
|
||||
CPOOL_LOCK(cpool);
|
||||
if(cpool->num_conn > maxconnects) {
|
||||
infof(data, "Connection pool is full, closing the oldest one");
|
||||
|
||||
conn_candidate = Curl_conncache_extract_oldest(data);
|
||||
if(conn_candidate) {
|
||||
/* Use the closure handle for this disconnect so that anything that
|
||||
happens during the disconnect is not stored and associated with the
|
||||
'data' handle which already just finished a transfer and it is
|
||||
important that details from this (unrelated) disconnect does not
|
||||
taint meta-data in the data handle. */
|
||||
struct conncache *connc = data->state.conn_cache;
|
||||
connc_disconnect(NULL, conn_candidate, connc, TRUE);
|
||||
oldest_idle = cpool_get_oldest_idle(cpool);
|
||||
kept = (oldest_idle != conn);
|
||||
if(oldest_idle) {
|
||||
Curl_cpool_disconnect(cpool->idata, oldest_idle, FALSE);
|
||||
}
|
||||
}
|
||||
if(do_lock)
|
||||
CPOOL_UNLOCK(cpool);
|
||||
}
|
||||
|
||||
return (conn_candidate == conn) ? FALSE : TRUE;
|
||||
|
||||
return kept;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function finds the connection in the connection bundle that has been
|
||||
* unused for the longest time.
|
||||
*
|
||||
* Does not lock the connection cache!
|
||||
*
|
||||
* Returns the pointer to the oldest idle connection, or NULL if none was
|
||||
* found.
|
||||
*/
|
||||
struct connectdata *
|
||||
Curl_conncache_extract_bundle(struct Curl_easy *data,
|
||||
struct connectbundle *bundle)
|
||||
static struct connectdata *
|
||||
cpool_bundle_get_oldest_idle(struct cpool_bundle *bundle)
|
||||
{
|
||||
struct Curl_llist_element *curr;
|
||||
struct Curl_llist_node *curr;
|
||||
timediff_t highscore = -1;
|
||||
timediff_t score;
|
||||
struct curltime now;
|
||||
struct connectdata *conn_candidate = NULL;
|
||||
struct connectdata *oldest_idle = NULL;
|
||||
struct connectdata *conn;
|
||||
|
||||
(void)data;
|
||||
|
||||
now = Curl_now();
|
||||
|
||||
curr = bundle->conn_list.head;
|
||||
curr = Curl_llist_head(&bundle->conns);
|
||||
while(curr) {
|
||||
conn = curr->ptr;
|
||||
conn = Curl_node_elem(curr);
|
||||
|
||||
if(!CONN_INUSE(conn)) {
|
||||
/* Set higher score for the age passed since the connection was used */
|
||||
@@ -472,130 +543,126 @@ Curl_conncache_extract_bundle(struct Curl_easy *data,
|
||||
|
||||
if(score > highscore) {
|
||||
highscore = score;
|
||||
conn_candidate = conn;
|
||||
oldest_idle = conn;
|
||||
}
|
||||
}
|
||||
curr = curr->next;
|
||||
curr = Curl_node_next(curr);
|
||||
}
|
||||
if(conn_candidate) {
|
||||
/* remove it to prevent another thread from nicking it */
|
||||
bundle_remove_conn(bundle, conn_candidate);
|
||||
data->state.conn_cache->num_conn--;
|
||||
DEBUGF(infof(data, "The cache now contains %zu members",
|
||||
data->state.conn_cache->num_conn));
|
||||
}
|
||||
|
||||
return conn_candidate;
|
||||
return oldest_idle;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function finds the connection in the connection cache that has been
|
||||
* unused for the longest time and extracts that from the bundle.
|
||||
*
|
||||
* Returns the pointer to the connection, or NULL if none was found.
|
||||
*/
|
||||
struct connectdata *
|
||||
Curl_conncache_extract_oldest(struct Curl_easy *data)
|
||||
static struct connectdata *cpool_get_oldest_idle(struct cpool *cpool)
|
||||
{
|
||||
struct conncache *connc = data->state.conn_cache;
|
||||
struct Curl_hash_iterator iter;
|
||||
struct Curl_llist_element *curr;
|
||||
struct Curl_llist_node *curr;
|
||||
struct Curl_hash_element *he;
|
||||
struct connectdata *oldest_idle = NULL;
|
||||
struct cpool_bundle *bundle;
|
||||
struct curltime now;
|
||||
timediff_t highscore =- 1;
|
||||
timediff_t score;
|
||||
struct curltime now;
|
||||
struct connectdata *conn_candidate = NULL;
|
||||
struct connectbundle *bundle;
|
||||
struct connectbundle *bundle_candidate = NULL;
|
||||
|
||||
now = Curl_now();
|
||||
Curl_hash_start_iterate(&cpool->dest2bundle, &iter);
|
||||
|
||||
CONNCACHE_LOCK(data);
|
||||
Curl_hash_start_iterate(&connc->hash, &iter);
|
||||
|
||||
he = Curl_hash_next_element(&iter);
|
||||
while(he) {
|
||||
for(he = Curl_hash_next_element(&iter); he;
|
||||
he = Curl_hash_next_element(&iter)) {
|
||||
struct connectdata *conn;
|
||||
|
||||
bundle = he->ptr;
|
||||
|
||||
curr = bundle->conn_list.head;
|
||||
while(curr) {
|
||||
conn = curr->ptr;
|
||||
|
||||
if(!CONN_INUSE(conn) && !conn->bits.close &&
|
||||
!conn->connect_only) {
|
||||
/* Set higher score for the age passed since the connection was used */
|
||||
score = Curl_timediff(now, conn->lastused);
|
||||
|
||||
if(score > highscore) {
|
||||
highscore = score;
|
||||
conn_candidate = conn;
|
||||
bundle_candidate = bundle;
|
||||
}
|
||||
for(curr = Curl_llist_head(&bundle->conns); curr;
|
||||
curr = Curl_node_next(curr)) {
|
||||
conn = Curl_node_elem(curr);
|
||||
if(CONN_INUSE(conn) || conn->bits.close || conn->connect_only)
|
||||
continue;
|
||||
/* Set higher score for the age passed since the connection was used */
|
||||
score = Curl_timediff(now, conn->lastused);
|
||||
if(score > highscore) {
|
||||
highscore = score;
|
||||
oldest_idle = conn;
|
||||
}
|
||||
curr = curr->next;
|
||||
}
|
||||
|
||||
he = Curl_hash_next_element(&iter);
|
||||
}
|
||||
if(conn_candidate) {
|
||||
/* remove it to prevent another thread from nicking it */
|
||||
bundle_remove_conn(bundle_candidate, conn_candidate);
|
||||
connc->num_conn--;
|
||||
DEBUGF(infof(data, "The cache now contains %zu members",
|
||||
connc->num_conn));
|
||||
}
|
||||
CONNCACHE_UNLOCK(data);
|
||||
|
||||
return conn_candidate;
|
||||
return oldest_idle;
|
||||
}
|
||||
|
||||
static void connc_shutdown_discard_all(struct conncache *connc)
|
||||
bool Curl_cpool_find(struct Curl_easy *data,
|
||||
const char *destination, size_t dest_len,
|
||||
Curl_cpool_conn_match_cb *conn_cb,
|
||||
Curl_cpool_done_match_cb *done_cb,
|
||||
void *userdata)
|
||||
{
|
||||
struct Curl_llist_element *e = connc->shutdowns.conn_list.head;
|
||||
struct cpool *cpool = cpool_get_instance(data);
|
||||
struct cpool_bundle *bundle;
|
||||
bool result = FALSE;
|
||||
|
||||
DEBUGASSERT(cpool);
|
||||
DEBUGASSERT(conn_cb);
|
||||
if(!cpool)
|
||||
return FALSE;
|
||||
|
||||
CPOOL_LOCK(cpool);
|
||||
bundle = Curl_hash_pick(&cpool->dest2bundle, (void *)destination, dest_len);
|
||||
if(bundle) {
|
||||
struct Curl_llist_node *curr = Curl_llist_head(&bundle->conns);
|
||||
while(curr) {
|
||||
struct connectdata *conn = Curl_node_elem(curr);
|
||||
/* Get next node now. callback might discard current */
|
||||
curr = Curl_node_next(curr);
|
||||
|
||||
if(conn_cb(conn, userdata)) {
|
||||
result = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(done_cb) {
|
||||
result = done_cb(result, userdata);
|
||||
}
|
||||
CPOOL_UNLOCK(cpool);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void cpool_shutdown_discard_all(struct cpool *cpool)
|
||||
{
|
||||
struct Curl_llist_node *e = Curl_llist_head(&cpool->shutdowns);
|
||||
struct connectdata *conn;
|
||||
|
||||
if(!e)
|
||||
return;
|
||||
|
||||
DEBUGF(infof(connc->closure_handle, "conncache_shutdown_discard_all"));
|
||||
DEBUGASSERT(!connc->shutdowns.iter_locked);
|
||||
connc->shutdowns.iter_locked = TRUE;
|
||||
DEBUGF(infof(cpool->idata, "cpool_shutdown_discard_all"));
|
||||
while(e) {
|
||||
conn = e->ptr;
|
||||
Curl_llist_remove(&connc->shutdowns.conn_list, e, NULL);
|
||||
DEBUGF(infof(connc->closure_handle, "discard connection #%"
|
||||
CURL_FORMAT_CURL_OFF_T, conn->connection_id));
|
||||
connc_disconnect(NULL, conn, connc, FALSE);
|
||||
e = connc->shutdowns.conn_list.head;
|
||||
conn = Curl_node_elem(e);
|
||||
Curl_node_remove(e);
|
||||
DEBUGF(infof(cpool->idata, "discard connection #%" FMT_OFF_T,
|
||||
conn->connection_id));
|
||||
cpool_close_and_destroy(cpool, conn, NULL, FALSE);
|
||||
e = Curl_llist_head(&cpool->shutdowns);
|
||||
}
|
||||
connc->shutdowns.iter_locked = FALSE;
|
||||
}
|
||||
|
||||
static void connc_close_all(struct conncache *connc)
|
||||
static void cpool_close_and_destroy_all(struct cpool *cpool)
|
||||
{
|
||||
struct Curl_easy *data = connc->closure_handle;
|
||||
struct connectdata *conn;
|
||||
int timeout_ms = 0;
|
||||
SIGPIPE_VARIABLE(pipe_st);
|
||||
|
||||
if(!data)
|
||||
return;
|
||||
|
||||
DEBUGASSERT(cpool);
|
||||
/* Move all connections to the shutdown list */
|
||||
sigpipe_init(&pipe_st);
|
||||
conn = connc_find_first_connection(connc);
|
||||
CPOOL_LOCK(cpool);
|
||||
conn = cpool_get_live_conn(cpool);
|
||||
while(conn) {
|
||||
connc_remove_conn(connc, conn);
|
||||
sigpipe_apply(data, &pipe_st);
|
||||
/* This will remove the connection from the cache */
|
||||
cpool_remove_conn(cpool, conn);
|
||||
sigpipe_apply(cpool->idata, &pipe_st);
|
||||
connclose(conn, "kill all");
|
||||
Curl_conncache_remove_conn(connc->closure_handle, conn, TRUE);
|
||||
connc_discard_conn(connc, connc->closure_handle, conn, FALSE);
|
||||
cpool_discard_conn(cpool, cpool->idata, conn, FALSE);
|
||||
|
||||
conn = connc_find_first_connection(connc);
|
||||
conn = cpool_get_live_conn(cpool);
|
||||
}
|
||||
CPOOL_UNLOCK(cpool);
|
||||
|
||||
/* Just for testing, run graceful shutdown */
|
||||
#ifdef DEBUGBUILD
|
||||
@@ -608,73 +675,53 @@ static void connc_close_all(struct conncache *connc)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
connc_shutdown_all(connc, timeout_ms);
|
||||
sigpipe_apply(cpool->idata, &pipe_st);
|
||||
cpool_shutdown_all(cpool, cpool->idata, timeout_ms);
|
||||
|
||||
/* discard all connections in the shutdown list */
|
||||
connc_shutdown_discard_all(connc);
|
||||
cpool_shutdown_discard_all(cpool);
|
||||
|
||||
sigpipe_apply(data, &pipe_st);
|
||||
Curl_hostcache_clean(data, data->dns.hostcache);
|
||||
Curl_close(&data);
|
||||
Curl_hostcache_clean(cpool->idata, cpool->idata->dns.hostcache);
|
||||
sigpipe_restore(&pipe_st);
|
||||
}
|
||||
|
||||
void Curl_conncache_close_all_connections(struct conncache *connc)
|
||||
{
|
||||
connc_close_all(connc);
|
||||
}
|
||||
|
||||
static void connc_shutdown_discard_oldest(struct conncache *connc)
|
||||
static void cpool_shutdown_destroy_oldest(struct cpool *cpool)
|
||||
{
|
||||
struct Curl_llist_element *e;
|
||||
struct Curl_llist_node *e;
|
||||
struct connectdata *conn;
|
||||
|
||||
DEBUGASSERT(!connc->shutdowns.iter_locked);
|
||||
if(connc->shutdowns.iter_locked)
|
||||
return;
|
||||
|
||||
e = connc->shutdowns.conn_list.head;
|
||||
e = Curl_llist_head(&cpool->shutdowns);
|
||||
if(e) {
|
||||
SIGPIPE_VARIABLE(pipe_st);
|
||||
conn = e->ptr;
|
||||
Curl_llist_remove(&connc->shutdowns.conn_list, e, NULL);
|
||||
conn = Curl_node_elem(e);
|
||||
Curl_node_remove(e);
|
||||
sigpipe_init(&pipe_st);
|
||||
sigpipe_apply(connc->closure_handle, &pipe_st);
|
||||
connc_disconnect(NULL, conn, connc, FALSE);
|
||||
sigpipe_apply(cpool->idata, &pipe_st);
|
||||
cpool_close_and_destroy(cpool, conn, NULL, FALSE);
|
||||
sigpipe_restore(&pipe_st);
|
||||
}
|
||||
}
|
||||
|
||||
static void connc_discard_conn(struct conncache *connc,
|
||||
struct Curl_easy *last_data,
|
||||
static void cpool_discard_conn(struct cpool *cpool,
|
||||
struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
bool aborted)
|
||||
{
|
||||
/* `last_data`, if present, is the transfer that last worked with
|
||||
* the connection. It is present when the connection is being shut down
|
||||
* via `Curl_conncache_discard_conn()`, e.g. when the transfer failed
|
||||
* or does not allow connection reuse.
|
||||
* Using the original handle is necessary for shutting down the protocol
|
||||
* handler belonging to the connection. Protocols like 'file:' rely on
|
||||
* being invoked to clean up their allocations in the easy handle.
|
||||
* When a connection comes from the cache, the transfer is no longer
|
||||
* there and we use the cache is own closure handle.
|
||||
*/
|
||||
struct Curl_easy *data = last_data? last_data : connc->closure_handle;
|
||||
bool done = FALSE;
|
||||
|
||||
DEBUGASSERT(data);
|
||||
DEBUGASSERT(connc);
|
||||
DEBUGASSERT(!conn->bundle);
|
||||
DEBUGASSERT(cpool);
|
||||
DEBUGASSERT(!conn->bits.in_cpool);
|
||||
|
||||
/*
|
||||
* If this connection is not marked to force-close, leave it open if there
|
||||
* are other users of it
|
||||
*/
|
||||
if(CONN_INUSE(conn) && !aborted) {
|
||||
DEBUGF(infof(data, "[CCACHE] not discarding #%" CURL_FORMAT_CURL_OFF_T
|
||||
" still in use by %zu transfers", conn->connection_id,
|
||||
CONN_INUSE(conn)));
|
||||
DEBUGF(infof(data, "[CCACHE] not discarding #%" FMT_OFF_T
|
||||
" still in use by %zu transfers", conn->connection_id,
|
||||
CONN_INUSE(conn)));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -694,22 +741,14 @@ static void connc_discard_conn(struct conncache *connc,
|
||||
if(!done) {
|
||||
/* Attempt to shutdown the connection right away. */
|
||||
Curl_attach_connection(data, conn);
|
||||
connc_run_conn_shutdown(data, conn, &done);
|
||||
DEBUGF(infof(data, "[CCACHE] shutdown #%" CURL_FORMAT_CURL_OFF_T
|
||||
", done=%d",conn->connection_id, done));
|
||||
cpool_run_conn_shutdown(data, conn, &done);
|
||||
DEBUGF(infof(data, "[CCACHE] shutdown #%" FMT_OFF_T ", done=%d",
|
||||
conn->connection_id, done));
|
||||
Curl_detach_connection(data);
|
||||
}
|
||||
|
||||
if(done) {
|
||||
connc_disconnect(data, conn, connc, FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUGASSERT(!connc->shutdowns.iter_locked);
|
||||
if(connc->shutdowns.iter_locked) {
|
||||
DEBUGF(infof(data, "[CCACHE] discarding #%" CURL_FORMAT_CURL_OFF_T
|
||||
", list locked", conn->connection_id));
|
||||
connc_disconnect(data, conn, connc, FALSE);
|
||||
cpool_close_and_destroy(cpool, conn, data, FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -717,65 +756,89 @@ static void connc_discard_conn(struct conncache *connc,
|
||||
* during multi processing. */
|
||||
if(data->multi && data->multi->max_shutdown_connections > 0 &&
|
||||
(data->multi->max_shutdown_connections >=
|
||||
(long)Curl_llist_count(&connc->shutdowns.conn_list))) {
|
||||
(long)Curl_llist_count(&cpool->shutdowns))) {
|
||||
DEBUGF(infof(data, "[CCACHE] discarding oldest shutdown connection "
|
||||
"due to limit of %ld",
|
||||
data->multi->max_shutdown_connections));
|
||||
connc_shutdown_discard_oldest(connc);
|
||||
cpool_shutdown_destroy_oldest(cpool);
|
||||
}
|
||||
|
||||
if(data->multi && data->multi->socket_cb) {
|
||||
DEBUGASSERT(connc == &data->multi->conn_cache);
|
||||
DEBUGASSERT(cpool == &data->multi->cpool);
|
||||
/* Start with an empty shutdown pollset, so out internal closure handle
|
||||
* is added to the sockets. */
|
||||
memset(&conn->shutdown_poll, 0, sizeof(conn->shutdown_poll));
|
||||
if(connc_update_shutdown_ev(data->multi, connc->closure_handle, conn)) {
|
||||
if(cpool_update_shutdown_ev(data->multi, cpool->idata, conn)) {
|
||||
DEBUGF(infof(data, "[CCACHE] update events for shutdown failed, "
|
||||
"discarding #%" CURL_FORMAT_CURL_OFF_T,
|
||||
conn->connection_id));
|
||||
connc_disconnect(data, conn, connc, FALSE);
|
||||
"discarding #%" FMT_OFF_T,
|
||||
conn->connection_id));
|
||||
cpool_close_and_destroy(cpool, conn, data, FALSE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Curl_llist_append(&connc->shutdowns.conn_list, conn, &conn->bundle_node);
|
||||
DEBUGF(infof(data, "[CCACHE] added #%" CURL_FORMAT_CURL_OFF_T
|
||||
" to shutdown list of length %zu", conn->connection_id,
|
||||
Curl_llist_count(&connc->shutdowns.conn_list)));
|
||||
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)));
|
||||
}
|
||||
|
||||
void Curl_conncache_disconnect(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
bool aborted)
|
||||
void Curl_cpool_disconnect(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
bool aborted)
|
||||
{
|
||||
DEBUGASSERT(data);
|
||||
/* Connection must no longer be in and connection cache */
|
||||
DEBUGASSERT(!conn->bundle);
|
||||
struct cpool *cpool = cpool_get_instance(data);
|
||||
bool do_lock;
|
||||
|
||||
DEBUGASSERT(cpool);
|
||||
DEBUGASSERT(data && !data->conn);
|
||||
if(!cpool)
|
||||
return;
|
||||
|
||||
/* If this connection is not marked to force-close, leave it open if there
|
||||
* are other users of it */
|
||||
if(CONN_INUSE(conn) && !aborted) {
|
||||
DEBUGASSERT(0); /* does this ever happen? */
|
||||
DEBUGF(infof(data, "Curl_disconnect when inuse: %zu", CONN_INUSE(conn)));
|
||||
return;
|
||||
}
|
||||
|
||||
/* This method may be called while we are under lock, e.g. from a
|
||||
* user callback in find. */
|
||||
do_lock = !CPOOL_IS_LOCKED(cpool);
|
||||
if(do_lock)
|
||||
CPOOL_LOCK(cpool);
|
||||
|
||||
if(conn->bits.in_cpool) {
|
||||
cpool_remove_conn(cpool, conn);
|
||||
DEBUGASSERT(!conn->bits.in_cpool);
|
||||
}
|
||||
|
||||
/* Run the callback to let it clean up anything it wants to. */
|
||||
aborted = cpool->disconnect_cb(data, conn, aborted);
|
||||
|
||||
if(data->multi) {
|
||||
/* Add it to the multi's conncache for shutdown handling */
|
||||
infof(data, "%s connection #%" CURL_FORMAT_CURL_OFF_T,
|
||||
/* Add it to the multi's cpool for shutdown handling */
|
||||
infof(data, "%s connection #%" FMT_OFF_T,
|
||||
aborted? "closing" : "shutting down", conn->connection_id);
|
||||
connc_discard_conn(&data->multi->conn_cache, data, conn, aborted);
|
||||
cpool_discard_conn(&data->multi->cpool, data, conn, aborted);
|
||||
}
|
||||
else {
|
||||
/* No multi available. Make a best-effort shutdown + close */
|
||||
infof(data, "closing connection #%" CURL_FORMAT_CURL_OFF_T,
|
||||
conn->connection_id);
|
||||
DEBUGASSERT(!conn->bundle);
|
||||
connc_run_conn_shutdown_handler(data, conn);
|
||||
connc_disconnect(data, conn, NULL, !aborted);
|
||||
infof(data, "closing connection #%" FMT_OFF_T, conn->connection_id);
|
||||
cpool_close_and_destroy(NULL, conn, data, !aborted);
|
||||
}
|
||||
|
||||
if(do_lock)
|
||||
CPOOL_UNLOCK(cpool);
|
||||
}
|
||||
|
||||
static void connc_run_conn_shutdown_handler(struct Curl_easy *data,
|
||||
static void cpool_run_conn_shutdown_handler(struct Curl_easy *data,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
if(!conn->bits.shutdown_handler) {
|
||||
if(conn->dns_entry) {
|
||||
Curl_resolv_unlock(data, conn->dns_entry);
|
||||
conn->dns_entry = NULL;
|
||||
}
|
||||
if(conn->dns_entry)
|
||||
Curl_resolv_unlink(data, &conn->dns_entry);
|
||||
|
||||
/* Cleanup NTLM connection-related data */
|
||||
Curl_http_auth_cleanup_ntlm(conn);
|
||||
@@ -785,9 +848,10 @@ static void connc_run_conn_shutdown_handler(struct Curl_easy *data,
|
||||
|
||||
if(conn->handler && conn->handler->disconnect) {
|
||||
/* This is set if protocol-specific cleanups should be made */
|
||||
DEBUGF(infof(data, "connection #%" CURL_FORMAT_CURL_OFF_T
|
||||
DEBUGF(infof(data, "connection #%" FMT_OFF_T
|
||||
", shutdown protocol handler (aborted=%d)",
|
||||
conn->connection_id, conn->bits.aborted));
|
||||
|
||||
conn->handler->disconnect(data, conn, conn->bits.aborted);
|
||||
}
|
||||
|
||||
@@ -798,7 +862,7 @@ static void connc_run_conn_shutdown_handler(struct Curl_easy *data,
|
||||
}
|
||||
}
|
||||
|
||||
static void connc_run_conn_shutdown(struct Curl_easy *data,
|
||||
static void cpool_run_conn_shutdown(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
bool *done)
|
||||
{
|
||||
@@ -808,7 +872,7 @@ static void connc_run_conn_shutdown(struct Curl_easy *data,
|
||||
/* We expect to be attached when called */
|
||||
DEBUGASSERT(data->conn == conn);
|
||||
|
||||
connc_run_conn_shutdown_handler(data, conn);
|
||||
cpool_run_conn_shutdown_handler(data, conn);
|
||||
|
||||
if(conn->bits.shutdown_filters) {
|
||||
*done = TRUE;
|
||||
@@ -835,24 +899,23 @@ static void connc_run_conn_shutdown(struct Curl_easy *data,
|
||||
conn->bits.shutdown_filters = TRUE;
|
||||
}
|
||||
|
||||
CURLcode Curl_conncache_add_pollfds(struct conncache *connc,
|
||||
struct curl_pollfds *cpfds)
|
||||
static CURLcode cpool_add_pollfds(struct cpool *cpool,
|
||||
struct curl_pollfds *cpfds)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
DEBUGASSERT(!connc->shutdowns.iter_locked);
|
||||
connc->shutdowns.iter_locked = TRUE;
|
||||
if(connc->shutdowns.conn_list.head) {
|
||||
struct Curl_llist_element *e;
|
||||
if(Curl_llist_head(&cpool->shutdowns)) {
|
||||
struct Curl_llist_node *e;
|
||||
struct easy_pollset ps;
|
||||
struct connectdata *conn;
|
||||
|
||||
for(e = connc->shutdowns.conn_list.head; e; e = e->next) {
|
||||
conn = e->ptr;
|
||||
for(e = Curl_llist_head(&cpool->shutdowns); e;
|
||||
e = Curl_node_next(e)) {
|
||||
conn = Curl_node_elem(e);
|
||||
memset(&ps, 0, sizeof(ps));
|
||||
Curl_attach_connection(connc->closure_handle, conn);
|
||||
Curl_conn_adjust_pollset(connc->closure_handle, &ps);
|
||||
Curl_detach_connection(connc->closure_handle);
|
||||
Curl_attach_connection(cpool->idata, conn);
|
||||
Curl_conn_adjust_pollset(cpool->idata, &ps);
|
||||
Curl_detach_connection(cpool->idata);
|
||||
|
||||
result = Curl_pollfds_add_ps(cpfds, &ps);
|
||||
if(result) {
|
||||
@@ -862,28 +925,37 @@ CURLcode Curl_conncache_add_pollfds(struct conncache *connc,
|
||||
}
|
||||
}
|
||||
out:
|
||||
connc->shutdowns.iter_locked = FALSE;
|
||||
return result;
|
||||
}
|
||||
|
||||
CURLcode Curl_conncache_add_waitfds(struct conncache *connc,
|
||||
struct curl_waitfds *cwfds)
|
||||
CURLcode Curl_cpool_add_pollfds(struct cpool *cpool,
|
||||
struct curl_pollfds *cpfds)
|
||||
{
|
||||
CURLcode result;
|
||||
CPOOL_LOCK(cpool);
|
||||
result = cpool_add_pollfds(cpool, cpfds);
|
||||
CPOOL_UNLOCK(cpool);
|
||||
return result;
|
||||
}
|
||||
|
||||
CURLcode Curl_cpool_add_waitfds(struct cpool *cpool,
|
||||
struct curl_waitfds *cwfds)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
DEBUGASSERT(!connc->shutdowns.iter_locked);
|
||||
connc->shutdowns.iter_locked = TRUE;
|
||||
if(connc->shutdowns.conn_list.head) {
|
||||
struct Curl_llist_element *e;
|
||||
CPOOL_LOCK(cpool);
|
||||
if(Curl_llist_head(&cpool->shutdowns)) {
|
||||
struct Curl_llist_node *e;
|
||||
struct easy_pollset ps;
|
||||
struct connectdata *conn;
|
||||
|
||||
for(e = connc->shutdowns.conn_list.head; e; e = e->next) {
|
||||
conn = e->ptr;
|
||||
for(e = Curl_llist_head(&cpool->shutdowns); e;
|
||||
e = Curl_node_next(e)) {
|
||||
conn = Curl_node_elem(e);
|
||||
memset(&ps, 0, sizeof(ps));
|
||||
Curl_attach_connection(connc->closure_handle, conn);
|
||||
Curl_conn_adjust_pollset(connc->closure_handle, &ps);
|
||||
Curl_detach_connection(connc->closure_handle);
|
||||
Curl_attach_connection(cpool->idata, conn);
|
||||
Curl_conn_adjust_pollset(cpool->idata, &ps);
|
||||
Curl_detach_connection(cpool->idata);
|
||||
|
||||
result = Curl_waitfds_add_ps(cwfds, &ps);
|
||||
if(result)
|
||||
@@ -891,15 +963,15 @@ CURLcode Curl_conncache_add_waitfds(struct conncache *connc,
|
||||
}
|
||||
}
|
||||
out:
|
||||
connc->shutdowns.iter_locked = FALSE;
|
||||
CPOOL_UNLOCK(cpool);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void connc_perform(struct conncache *connc)
|
||||
static void cpool_perform(struct cpool *cpool)
|
||||
{
|
||||
struct Curl_easy *data = connc->closure_handle;
|
||||
struct Curl_llist_element *e = connc->shutdowns.conn_list.head;
|
||||
struct Curl_llist_element *enext;
|
||||
struct Curl_easy *data = cpool->idata;
|
||||
struct Curl_llist_node *e = Curl_llist_head(&cpool->shutdowns);
|
||||
struct Curl_llist_node *enext;
|
||||
struct connectdata *conn;
|
||||
struct curltime *nowp = NULL;
|
||||
struct curltime now;
|
||||
@@ -910,21 +982,19 @@ static void connc_perform(struct conncache *connc)
|
||||
return;
|
||||
|
||||
DEBUGASSERT(data);
|
||||
DEBUGASSERT(!connc->shutdowns.iter_locked);
|
||||
DEBUGF(infof(data, "[CCACHE] perform, %zu connections being shutdown",
|
||||
Curl_llist_count(&connc->shutdowns.conn_list)));
|
||||
connc->shutdowns.iter_locked = TRUE;
|
||||
Curl_llist_count(&cpool->shutdowns)));
|
||||
while(e) {
|
||||
enext = e->next;
|
||||
conn = e->ptr;
|
||||
enext = Curl_node_next(e);
|
||||
conn = Curl_node_elem(e);
|
||||
Curl_attach_connection(data, conn);
|
||||
connc_run_conn_shutdown(data, conn, &done);
|
||||
DEBUGF(infof(data, "[CCACHE] shutdown #%" CURL_FORMAT_CURL_OFF_T
|
||||
", done=%d", conn->connection_id, done));
|
||||
cpool_run_conn_shutdown(data, conn, &done);
|
||||
DEBUGF(infof(data, "[CCACHE] shutdown #%" FMT_OFF_T ", done=%d",
|
||||
conn->connection_id, done));
|
||||
Curl_detach_connection(data);
|
||||
if(done) {
|
||||
Curl_llist_remove(&connc->shutdowns.conn_list, e, NULL);
|
||||
connc_disconnect(NULL, conn, connc, FALSE);
|
||||
Curl_node_remove(e);
|
||||
cpool_close_and_destroy(cpool, conn, NULL, FALSE);
|
||||
}
|
||||
else {
|
||||
/* Not done, when does this connection time out? */
|
||||
@@ -938,72 +1008,56 @@ static void connc_perform(struct conncache *connc)
|
||||
}
|
||||
e = enext;
|
||||
}
|
||||
connc->shutdowns.iter_locked = FALSE;
|
||||
|
||||
if(next_from_now_ms)
|
||||
Curl_expire(data, next_from_now_ms, EXPIRE_RUN_NOW);
|
||||
}
|
||||
|
||||
void Curl_conncache_multi_perform(struct Curl_multi *multi)
|
||||
void Curl_cpool_multi_perform(struct Curl_multi *multi)
|
||||
{
|
||||
connc_perform(&multi->conn_cache);
|
||||
CPOOL_LOCK(&multi->cpool);
|
||||
cpool_perform(&multi->cpool);
|
||||
CPOOL_UNLOCK(&multi->cpool);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Disconnects the given connection. Note the connection may not be the
|
||||
* primary connection, like when freeing room in the connection cache or
|
||||
* killing of a dead old connection.
|
||||
*
|
||||
* A connection needs an easy handle when closing down. We support this passed
|
||||
* in separately since the connection to get closed here is often already
|
||||
* disassociated from an easy handle.
|
||||
*
|
||||
* This function MUST NOT reset state in the Curl_easy struct if that
|
||||
* is not strictly bound to the life-time of *this* particular connection.
|
||||
*
|
||||
* Close and destroy the connection. Run the shutdown sequence once,
|
||||
* of so requested.
|
||||
*/
|
||||
static void connc_disconnect(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
struct conncache *connc,
|
||||
bool do_shutdown)
|
||||
static void cpool_close_and_destroy(struct cpool *cpool,
|
||||
struct connectdata *conn,
|
||||
struct Curl_easy *data,
|
||||
bool do_shutdown)
|
||||
{
|
||||
bool done;
|
||||
|
||||
/* there must be a connection to close */
|
||||
DEBUGASSERT(conn);
|
||||
/* it must be removed from the connection cache */
|
||||
DEBUGASSERT(!conn->bundle);
|
||||
/* it must be removed from the connection pool */
|
||||
DEBUGASSERT(!conn->bits.in_cpool);
|
||||
/* there must be an associated transfer */
|
||||
DEBUGASSERT(data || connc);
|
||||
DEBUGASSERT(data || cpool);
|
||||
if(!data)
|
||||
data = connc->closure_handle;
|
||||
data = cpool->idata;
|
||||
|
||||
/* the transfer must be detached from the connection */
|
||||
DEBUGASSERT(data && !data->conn);
|
||||
|
||||
Curl_attach_connection(data, conn);
|
||||
|
||||
if(connc && connc->multi && connc->multi->socket_cb) {
|
||||
struct easy_pollset ps;
|
||||
/* With an empty pollset, all previously polled sockets will be removed
|
||||
* via the multi_socket API callback. */
|
||||
memset(&ps, 0, sizeof(ps));
|
||||
(void)Curl_multi_pollset_ev(connc->multi, data, &ps, &conn->shutdown_poll);
|
||||
}
|
||||
|
||||
connc_run_conn_shutdown_handler(data, conn);
|
||||
cpool_run_conn_shutdown_handler(data, conn);
|
||||
if(do_shutdown) {
|
||||
/* Make a last attempt to shutdown handlers and filters, if
|
||||
* not done so already. */
|
||||
connc_run_conn_shutdown(data, conn, &done);
|
||||
cpool_run_conn_shutdown(data, conn, &done);
|
||||
}
|
||||
|
||||
if(connc)
|
||||
DEBUGF(infof(data, "[CCACHE] closing #%" CURL_FORMAT_CURL_OFF_T,
|
||||
if(cpool)
|
||||
DEBUGF(infof(data, "[CCACHE] closing #%" FMT_OFF_T,
|
||||
conn->connection_id));
|
||||
else
|
||||
DEBUGF(infof(data, "closing connection #%" CURL_FORMAT_CURL_OFF_T,
|
||||
DEBUGF(infof(data, "closing connection #%" FMT_OFF_T,
|
||||
conn->connection_id));
|
||||
Curl_conn_close(data, SECONDARYSOCKET);
|
||||
Curl_conn_close(data, FIRSTSOCKET);
|
||||
@@ -1013,7 +1067,7 @@ static void connc_disconnect(struct Curl_easy *data,
|
||||
}
|
||||
|
||||
|
||||
static CURLMcode connc_update_shutdown_ev(struct Curl_multi *multi,
|
||||
static CURLMcode cpool_update_shutdown_ev(struct Curl_multi *multi,
|
||||
struct Curl_easy *data,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
@@ -1036,49 +1090,41 @@ static CURLMcode connc_update_shutdown_ev(struct Curl_multi *multi,
|
||||
return mresult;
|
||||
}
|
||||
|
||||
void Curl_conncache_multi_socket(struct Curl_multi *multi,
|
||||
curl_socket_t s, int ev_bitmask)
|
||||
void Curl_cpool_multi_socket(struct Curl_multi *multi,
|
||||
curl_socket_t s, int ev_bitmask)
|
||||
{
|
||||
struct conncache *connc = &multi->conn_cache;
|
||||
struct Curl_easy *data = connc->closure_handle;
|
||||
struct Curl_llist_element *e = connc->shutdowns.conn_list.head;
|
||||
struct cpool *cpool = &multi->cpool;
|
||||
struct Curl_easy *data = cpool->idata;
|
||||
struct Curl_llist_node *e;
|
||||
struct connectdata *conn;
|
||||
bool done;
|
||||
|
||||
(void)ev_bitmask;
|
||||
DEBUGASSERT(multi->socket_cb);
|
||||
if(!e)
|
||||
return;
|
||||
|
||||
connc->shutdowns.iter_locked = TRUE;
|
||||
CPOOL_LOCK(cpool);
|
||||
e = Curl_llist_head(&cpool->shutdowns);
|
||||
while(e) {
|
||||
conn = e->ptr;
|
||||
conn = Curl_node_elem(e);
|
||||
if(s == conn->sock[FIRSTSOCKET] || s == conn->sock[SECONDARYSOCKET]) {
|
||||
Curl_attach_connection(data, conn);
|
||||
connc_run_conn_shutdown(data, conn, &done);
|
||||
DEBUGF(infof(data, "[CCACHE] shutdown #%" CURL_FORMAT_CURL_OFF_T
|
||||
", done=%d", conn->connection_id, done));
|
||||
cpool_run_conn_shutdown(data, conn, &done);
|
||||
DEBUGF(infof(data, "[CCACHE] shutdown #%" FMT_OFF_T ", done=%d",
|
||||
conn->connection_id, done));
|
||||
Curl_detach_connection(data);
|
||||
if(done || connc_update_shutdown_ev(multi, data, conn)) {
|
||||
Curl_llist_remove(&connc->shutdowns.conn_list, e, NULL);
|
||||
connc_disconnect(NULL, conn, connc, FALSE);
|
||||
if(done || cpool_update_shutdown_ev(multi, data, conn)) {
|
||||
Curl_node_remove(e);
|
||||
cpool_close_and_destroy(cpool, conn, NULL, FALSE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
e = e->next;
|
||||
e = Curl_node_next(e);
|
||||
}
|
||||
connc->shutdowns.iter_locked = FALSE;
|
||||
CPOOL_UNLOCK(cpool);
|
||||
}
|
||||
|
||||
void Curl_conncache_multi_close_all(struct Curl_multi *multi)
|
||||
{
|
||||
connc_close_all(&multi->conn_cache);
|
||||
}
|
||||
|
||||
|
||||
#define NUM_POLLS_ON_STACK 10
|
||||
|
||||
static CURLcode connc_shutdown_wait(struct conncache *connc, int timeout_ms)
|
||||
static CURLcode cpool_shutdown_wait(struct cpool *cpool, int timeout_ms)
|
||||
{
|
||||
struct pollfd a_few_on_stack[NUM_POLLS_ON_STACK];
|
||||
struct curl_pollfds cpfds;
|
||||
@@ -1086,7 +1132,7 @@ static CURLcode connc_shutdown_wait(struct conncache *connc, int timeout_ms)
|
||||
|
||||
Curl_pollfds_init(&cpfds, a_few_on_stack, NUM_POLLS_ON_STACK);
|
||||
|
||||
result = Curl_conncache_add_pollfds(connc, &cpfds);
|
||||
result = cpool_add_pollfds(cpool, &cpfds);
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
@@ -1097,9 +1143,9 @@ out:
|
||||
return result;
|
||||
}
|
||||
|
||||
static void connc_shutdown_all(struct conncache *connc, int timeout_ms)
|
||||
static void cpool_shutdown_all(struct cpool *cpool,
|
||||
struct Curl_easy *data, int timeout_ms)
|
||||
{
|
||||
struct Curl_easy *data = connc->closure_handle;
|
||||
struct connectdata *conn;
|
||||
struct curltime started = Curl_now();
|
||||
|
||||
@@ -1107,79 +1153,226 @@ static void connc_shutdown_all(struct conncache *connc, int timeout_ms)
|
||||
return;
|
||||
(void)data;
|
||||
|
||||
DEBUGF(infof(data, "conncache shutdown all"));
|
||||
DEBUGF(infof(data, "cpool shutdown all"));
|
||||
|
||||
/* Move all connections into the shutdown queue */
|
||||
conn = connc_find_first_connection(connc);
|
||||
while(conn) {
|
||||
/* This will remove the connection from the cache */
|
||||
DEBUGF(infof(data, "moving connection %" CURL_FORMAT_CURL_OFF_T
|
||||
for(conn = cpool_get_live_conn(cpool); conn;
|
||||
conn = cpool_get_live_conn(cpool)) {
|
||||
/* Move conn from live set to shutdown or destroy right away */
|
||||
DEBUGF(infof(data, "moving connection #%" FMT_OFF_T
|
||||
" to shutdown queue", conn->connection_id));
|
||||
connc_remove_conn(connc, conn);
|
||||
connc_discard_conn(connc, NULL, conn, FALSE);
|
||||
conn = connc_find_first_connection(connc);
|
||||
cpool_remove_conn(cpool, conn);
|
||||
cpool_discard_conn(cpool, data, conn, FALSE);
|
||||
}
|
||||
|
||||
DEBUGASSERT(!connc->shutdowns.iter_locked);
|
||||
while(connc->shutdowns.conn_list.head) {
|
||||
while(Curl_llist_head(&cpool->shutdowns)) {
|
||||
timediff_t timespent;
|
||||
int remain_ms;
|
||||
|
||||
connc_perform(connc);
|
||||
cpool_perform(cpool);
|
||||
|
||||
if(!connc->shutdowns.conn_list.head) {
|
||||
DEBUGF(infof(data, "conncache shutdown ok"));
|
||||
if(!Curl_llist_head(&cpool->shutdowns)) {
|
||||
DEBUGF(infof(data, "cpool shutdown ok"));
|
||||
break;
|
||||
}
|
||||
|
||||
/* wait for activity, timeout or "nothing" */
|
||||
timespent = Curl_timediff(Curl_now(), started);
|
||||
if(timespent >= (timediff_t)timeout_ms) {
|
||||
DEBUGF(infof(data, "conncache shutdown %s",
|
||||
DEBUGF(infof(data, "cpool shutdown %s",
|
||||
(timeout_ms > 0)? "timeout" : "best effort done"));
|
||||
break;
|
||||
}
|
||||
|
||||
remain_ms = timeout_ms - (int)timespent;
|
||||
if(connc_shutdown_wait(connc, remain_ms)) {
|
||||
DEBUGF(infof(data, "conncache shutdown all, abort"));
|
||||
if(cpool_shutdown_wait(cpool, remain_ms)) {
|
||||
DEBUGF(infof(data, "cpool shutdown all, abort"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Due to errors/timeout, we might come here without being full ydone. */
|
||||
connc_shutdown_discard_all(connc);
|
||||
/* Due to errors/timeout, we might come here without being done. */
|
||||
cpool_shutdown_discard_all(cpool);
|
||||
}
|
||||
|
||||
struct cpool_reaper_ctx {
|
||||
struct curltime now;
|
||||
};
|
||||
|
||||
static int cpool_reap_dead_cb(struct Curl_easy *data,
|
||||
struct connectdata *conn, void *param)
|
||||
{
|
||||
struct cpool_reaper_ctx *rctx = param;
|
||||
if(Curl_conn_seems_dead(conn, data, &rctx->now)) {
|
||||
/* stop the iteration here, pass back the connection that was pruned */
|
||||
Curl_cpool_disconnect(data, conn, FALSE);
|
||||
return 1;
|
||||
}
|
||||
return 0; /* continue iteration */
|
||||
}
|
||||
|
||||
/*
|
||||
* This function scans the data's connection pool for half-open/dead
|
||||
* connections, closes and removes them.
|
||||
* The cleanup is done at most once per second.
|
||||
*
|
||||
* When called, this transfer has no connection attached.
|
||||
*/
|
||||
void Curl_cpool_prune_dead(struct Curl_easy *data)
|
||||
{
|
||||
struct cpool *cpool = cpool_get_instance(data);
|
||||
struct cpool_reaper_ctx rctx;
|
||||
timediff_t elapsed;
|
||||
|
||||
if(!cpool)
|
||||
return;
|
||||
|
||||
rctx.now = Curl_now();
|
||||
CPOOL_LOCK(cpool);
|
||||
elapsed = Curl_timediff(rctx.now, cpool->last_cleanup);
|
||||
|
||||
if(elapsed >= 1000L) {
|
||||
while(cpool_foreach(data, cpool, &rctx, cpool_reap_dead_cb))
|
||||
;
|
||||
cpool->last_cleanup = rctx.now;
|
||||
}
|
||||
CPOOL_UNLOCK(cpool);
|
||||
}
|
||||
|
||||
static int conn_upkeep(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
void *param)
|
||||
{
|
||||
struct curltime *now = param;
|
||||
/* TODO, shall we reap connections that return an error here? */
|
||||
Curl_conn_upkeep(data, conn, now);
|
||||
return 0; /* continue iteration */
|
||||
}
|
||||
|
||||
CURLcode Curl_cpool_upkeep(void *data)
|
||||
{
|
||||
struct cpool *cpool = cpool_get_instance(data);
|
||||
struct curltime now = Curl_now();
|
||||
|
||||
if(!cpool)
|
||||
return CURLE_OK;
|
||||
|
||||
CPOOL_LOCK(cpool);
|
||||
cpool_foreach(data, cpool, &now, conn_upkeep);
|
||||
CPOOL_UNLOCK(cpool);
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
struct cpool_find_ctx {
|
||||
curl_off_t id;
|
||||
struct connectdata *conn;
|
||||
};
|
||||
|
||||
static int cpool_find_conn(struct Curl_easy *data,
|
||||
struct connectdata *conn, void *param)
|
||||
{
|
||||
struct cpool_find_ctx *fctx = param;
|
||||
(void)data;
|
||||
if(conn->connection_id == fctx->id) {
|
||||
fctx->conn = conn;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct connectdata *Curl_cpool_get_conn(struct Curl_easy *data,
|
||||
curl_off_t conn_id)
|
||||
{
|
||||
struct cpool *cpool = cpool_get_instance(data);
|
||||
struct cpool_find_ctx fctx;
|
||||
|
||||
if(!cpool)
|
||||
return NULL;
|
||||
fctx.id = conn_id;
|
||||
fctx.conn = NULL;
|
||||
CPOOL_LOCK(cpool);
|
||||
cpool_foreach(cpool->idata, cpool, &fctx, cpool_find_conn);
|
||||
CPOOL_UNLOCK(cpool);
|
||||
return fctx.conn;
|
||||
}
|
||||
|
||||
struct cpool_do_conn_ctx {
|
||||
curl_off_t id;
|
||||
Curl_cpool_conn_do_cb *cb;
|
||||
void *cbdata;
|
||||
};
|
||||
|
||||
static int cpool_do_conn(struct Curl_easy *data,
|
||||
struct connectdata *conn, void *param)
|
||||
{
|
||||
struct cpool_do_conn_ctx *dctx = param;
|
||||
(void)data;
|
||||
if(conn->connection_id == dctx->id) {
|
||||
dctx->cb(conn, data, dctx->cbdata);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Curl_cpool_do_by_id(struct Curl_easy *data, curl_off_t conn_id,
|
||||
Curl_cpool_conn_do_cb *cb, void *cbdata)
|
||||
{
|
||||
struct cpool *cpool = cpool_get_instance(data);
|
||||
struct cpool_do_conn_ctx dctx;
|
||||
|
||||
if(!cpool)
|
||||
return;
|
||||
dctx.id = conn_id;
|
||||
dctx.cb = cb;
|
||||
dctx.cbdata = cbdata;
|
||||
CPOOL_LOCK(cpool);
|
||||
cpool_foreach(data, cpool, &dctx, cpool_do_conn);
|
||||
CPOOL_UNLOCK(cpool);
|
||||
}
|
||||
|
||||
void Curl_cpool_do_locked(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
Curl_cpool_conn_do_cb *cb, void *cbdata)
|
||||
{
|
||||
struct cpool *cpool = cpool_get_instance(data);
|
||||
if(cpool) {
|
||||
CPOOL_LOCK(cpool);
|
||||
cb(conn, data, cbdata);
|
||||
CPOOL_UNLOCK(cpool);
|
||||
}
|
||||
else
|
||||
cb(conn, data, cbdata);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Useful for debugging the connection cache */
|
||||
void Curl_conncache_print(struct conncache *connc)
|
||||
/* Useful for debugging the connection pool */
|
||||
void Curl_cpool_print(struct cpool *cpool)
|
||||
{
|
||||
struct Curl_hash_iterator iter;
|
||||
struct Curl_llist_element *curr;
|
||||
struct Curl_llist_node *curr;
|
||||
struct Curl_hash_element *he;
|
||||
|
||||
if(!connc)
|
||||
if(!cpool)
|
||||
return;
|
||||
|
||||
fprintf(stderr, "=Bundle cache=\n");
|
||||
|
||||
Curl_hash_start_iterate(connc->hash, &iter);
|
||||
Curl_hash_start_iterate(cpool->dest2bundle, &iter);
|
||||
|
||||
he = Curl_hash_next_element(&iter);
|
||||
while(he) {
|
||||
struct connectbundle *bundle;
|
||||
struct cpool_bundle *bundle;
|
||||
struct connectdata *conn;
|
||||
|
||||
bundle = he->ptr;
|
||||
|
||||
fprintf(stderr, "%s -", he->key);
|
||||
curr = bundle->conn_list->head;
|
||||
curr = Curl_llist_head(bundle->conns);
|
||||
while(curr) {
|
||||
conn = curr->ptr;
|
||||
conn = Curl_node_elem(curr);
|
||||
|
||||
fprintf(stderr, " [%p %d]", (void *)conn, conn->inuse);
|
||||
curr = curr->next;
|
||||
fprintf(stderr, " [%p %d]", (void *)conn, conn->refcount);
|
||||
curr = Curl_node_next(curr);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
|
||||
+142
-105
@@ -25,140 +25,177 @@
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/*
|
||||
* All accesses to struct fields and changing of data in the connection cache
|
||||
* and connectbundles must be done with the conncache LOCKED. The cache might
|
||||
* be shared.
|
||||
*/
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include "timeval.h"
|
||||
|
||||
struct connectdata;
|
||||
struct Curl_easy;
|
||||
struct curl_pollfds;
|
||||
struct curl_waitfds;
|
||||
struct Curl_multi;
|
||||
struct Curl_share;
|
||||
|
||||
struct connshutdowns {
|
||||
struct Curl_llist conn_list; /* The connectdata to shut down */
|
||||
BIT(iter_locked); /* TRUE while iterating the list */
|
||||
};
|
||||
/**
|
||||
* Callback invoked when disconnecting connections.
|
||||
* @param data transfer last handling the connection, not attached
|
||||
* @param conn the connection to discard
|
||||
* @param aborted if the connection is being aborted
|
||||
* @return if the connection is being aborted, e.g. should NOT perform
|
||||
* a shutdown and just close.
|
||||
**/
|
||||
typedef bool Curl_cpool_disconnect_cb(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
bool aborted);
|
||||
|
||||
struct conncache {
|
||||
struct Curl_hash hash;
|
||||
struct cpool {
|
||||
/* the pooled connections, bundled per destination */
|
||||
struct Curl_hash dest2bundle;
|
||||
size_t num_conn;
|
||||
curl_off_t next_connection_id;
|
||||
curl_off_t next_easy_id;
|
||||
struct curltime last_cleanup;
|
||||
struct connshutdowns shutdowns;
|
||||
/* handle used for closing cached connections */
|
||||
struct Curl_easy *closure_handle;
|
||||
struct Curl_multi *multi; /* Optional, set if cache belongs to multi */
|
||||
struct Curl_llist shutdowns; /* The connections being shut down */
|
||||
struct Curl_easy *idata; /* internal handle used for discard */
|
||||
struct Curl_multi *multi; /* != NULL iff pool belongs to multi */
|
||||
struct Curl_share *share; /* != NULL iff pool belongs to share */
|
||||
Curl_cpool_disconnect_cb *disconnect_cb;
|
||||
BIT(locked);
|
||||
};
|
||||
|
||||
#define BUNDLE_NO_MULTIUSE -1
|
||||
#define BUNDLE_UNKNOWN 0 /* initial value */
|
||||
#define BUNDLE_MULTIPLEX 2
|
||||
|
||||
#ifdef DEBUGBUILD
|
||||
/* the debug versions of these macros make extra certain that the lock is
|
||||
never doubly locked or unlocked */
|
||||
#define CONNCACHE_LOCK(x) \
|
||||
do { \
|
||||
if((x)->share) { \
|
||||
Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, \
|
||||
CURL_LOCK_ACCESS_SINGLE); \
|
||||
DEBUGASSERT(!(x)->state.conncache_lock); \
|
||||
(x)->state.conncache_lock = TRUE; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define CONNCACHE_UNLOCK(x) \
|
||||
do { \
|
||||
if((x)->share) { \
|
||||
DEBUGASSERT((x)->state.conncache_lock); \
|
||||
(x)->state.conncache_lock = FALSE; \
|
||||
Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT); \
|
||||
} \
|
||||
} while(0)
|
||||
#else
|
||||
#define CONNCACHE_LOCK(x) if((x)->share) \
|
||||
Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE)
|
||||
#define CONNCACHE_UNLOCK(x) if((x)->share) \
|
||||
Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT)
|
||||
#endif
|
||||
|
||||
struct connectbundle {
|
||||
int multiuse; /* supports multi-use */
|
||||
size_t num_connections; /* Number of connections in the bundle */
|
||||
struct Curl_llist conn_list; /* The connectdata members of the bundle */
|
||||
};
|
||||
|
||||
/* Init the cache, pass multi only if cache is owned by it.
|
||||
/* Init the pool, pass multi only if pool is owned by it.
|
||||
* returns 1 on error, 0 is fine.
|
||||
*/
|
||||
int Curl_conncache_init(struct conncache *,
|
||||
struct Curl_multi *multi,
|
||||
size_t size);
|
||||
void Curl_conncache_destroy(struct conncache *connc);
|
||||
int Curl_cpool_init(struct cpool *cpool,
|
||||
Curl_cpool_disconnect_cb *disconnect_cb,
|
||||
struct Curl_multi *multi,
|
||||
struct Curl_share *share,
|
||||
size_t size);
|
||||
|
||||
/* return the correct bundle, to a host or a proxy */
|
||||
struct connectbundle *Curl_conncache_find_bundle(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
struct conncache *connc);
|
||||
/* returns number of connections currently held in the connection cache */
|
||||
size_t Curl_conncache_size(struct Curl_easy *data);
|
||||
/* Destroy all connections and free all members */
|
||||
void Curl_cpool_destroy(struct cpool *connc);
|
||||
|
||||
bool Curl_conncache_return_conn(struct Curl_easy *data,
|
||||
struct connectdata *conn);
|
||||
CURLcode Curl_conncache_add_conn(struct Curl_easy *data) WARN_UNUSED_RESULT;
|
||||
void Curl_conncache_remove_conn(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
bool lock);
|
||||
bool Curl_conncache_foreach(struct Curl_easy *data,
|
||||
struct conncache *connc,
|
||||
void *param,
|
||||
int (*func)(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
void *param));
|
||||
|
||||
struct connectdata *
|
||||
Curl_conncache_find_first_connection(struct conncache *connc);
|
||||
|
||||
struct connectdata *
|
||||
Curl_conncache_extract_bundle(struct Curl_easy *data,
|
||||
struct connectbundle *bundle);
|
||||
struct connectdata *
|
||||
Curl_conncache_extract_oldest(struct Curl_easy *data);
|
||||
void Curl_conncache_close_all_connections(struct conncache *connc);
|
||||
void Curl_conncache_print(struct conncache *connc);
|
||||
/* Init the transfer to be used within its connection pool.
|
||||
* Assigns `data->id`. */
|
||||
void Curl_cpool_xfer_init(struct Curl_easy *data);
|
||||
|
||||
/**
|
||||
* Tear down the connection. If `aborted` is FALSE, the connection
|
||||
* will be shut down first before discarding. If the shutdown
|
||||
* is not immediately complete, the connection
|
||||
* will be placed into the cache is shutdown queue.
|
||||
* Get the connection with the given id from the transfer's pool.
|
||||
*/
|
||||
void Curl_conncache_disconnect(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
bool aborted);
|
||||
struct connectdata *Curl_cpool_get_conn(struct Curl_easy *data,
|
||||
curl_off_t conn_id);
|
||||
|
||||
CURLcode Curl_cpool_add_conn(struct Curl_easy *data,
|
||||
struct connectdata *conn) WARN_UNUSED_RESULT;
|
||||
|
||||
/**
|
||||
* Add sockets and POLLIN/OUT flags for connections handled by the cache.
|
||||
* Return if the pool has reached its configured limits for adding
|
||||
* the given connection. Will try to discard the oldest, idle
|
||||
* connections to make space.
|
||||
*/
|
||||
CURLcode Curl_conncache_add_pollfds(struct conncache *connc,
|
||||
struct curl_pollfds *cpfds);
|
||||
CURLcode Curl_conncache_add_waitfds(struct conncache *connc,
|
||||
struct curl_waitfds *cwfds);
|
||||
#define CPOOL_LIMIT_OK 0
|
||||
#define CPOOL_LIMIT_DEST 1
|
||||
#define CPOOL_LIMIT_TOTAL 2
|
||||
int Curl_cpool_check_limits(struct Curl_easy *data,
|
||||
struct connectdata *conn);
|
||||
|
||||
/* Return of conn is suitable. If so, stops iteration. */
|
||||
typedef bool Curl_cpool_conn_match_cb(struct connectdata *conn,
|
||||
void *userdata);
|
||||
|
||||
/* Act on the result of the find, may override it. */
|
||||
typedef bool Curl_cpool_done_match_cb(bool result, void *userdata);
|
||||
|
||||
/**
|
||||
* Perform maintenance on connections in the cache. Specifically,
|
||||
* Find a connection in the pool matching `destination`.
|
||||
* All callbacks are invoked while the pool's lock is held.
|
||||
* @param data current transfer
|
||||
* @param destination match agaonst `conn->destination` in pool
|
||||
* @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.
|
||||
*/
|
||||
bool Curl_cpool_find(struct Curl_easy *data,
|
||||
const char *destination, size_t dest_len,
|
||||
Curl_cpool_conn_match_cb *conn_cb,
|
||||
Curl_cpool_done_match_cb *done_cb,
|
||||
void *userdata);
|
||||
|
||||
/*
|
||||
* A connection (already in the pool) is now idle. Do any
|
||||
* cleanups in regard to the pool's limits.
|
||||
*
|
||||
* Return TRUE if idle connection kept in pool, FALSE if closed.
|
||||
*/
|
||||
bool Curl_cpool_conn_now_idle(struct Curl_easy *data,
|
||||
struct connectdata *conn);
|
||||
|
||||
/**
|
||||
* Remove the connection from the pool and tear it down.
|
||||
* If `aborted` is FALSE, the connection will be shut down first
|
||||
* before closing and destroying it.
|
||||
* If the shutdown is not immediately complete, the connection
|
||||
* will be placed into the pool's shutdown queue.
|
||||
*/
|
||||
void Curl_cpool_disconnect(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
bool aborted);
|
||||
|
||||
/**
|
||||
* This function scans the data's connection pool for half-open/dead
|
||||
* connections, closes and removes them.
|
||||
* The cleanup is done at most once per second.
|
||||
*
|
||||
* When called, this transfer has no connection attached.
|
||||
*/
|
||||
void Curl_cpool_prune_dead(struct Curl_easy *data);
|
||||
|
||||
/**
|
||||
* Perform upkeep actions on connections in the transfer's pool.
|
||||
*/
|
||||
CURLcode Curl_cpool_upkeep(void *data);
|
||||
|
||||
typedef void Curl_cpool_conn_do_cb(struct connectdata *conn,
|
||||
struct Curl_easy *data,
|
||||
void *cbdata);
|
||||
|
||||
/**
|
||||
* Invoke the callback on the pool's connection with the
|
||||
* given connection id (if it exists).
|
||||
*/
|
||||
void Curl_cpool_do_by_id(struct Curl_easy *data,
|
||||
curl_off_t conn_id,
|
||||
Curl_cpool_conn_do_cb *cb, void *cbdata);
|
||||
|
||||
/**
|
||||
* Invoked the callback for the given data + connection under the
|
||||
* connection pool's lock.
|
||||
* The callback is always invoked, even if the transfer has no connection
|
||||
* pool associated.
|
||||
*/
|
||||
void Curl_cpool_do_locked(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
Curl_cpool_conn_do_cb *cb, void *cbdata);
|
||||
|
||||
/**
|
||||
* Add sockets and POLLIN/OUT flags for connections handled by the pool.
|
||||
*/
|
||||
CURLcode Curl_cpool_add_pollfds(struct cpool *connc,
|
||||
struct curl_pollfds *cpfds);
|
||||
CURLcode Curl_cpool_add_waitfds(struct cpool *connc,
|
||||
struct curl_waitfds *cwfds);
|
||||
|
||||
/**
|
||||
* Perform maintenance on connections in the pool. Specifically,
|
||||
* progress the shutdown of connections in the queue.
|
||||
*/
|
||||
void Curl_conncache_multi_perform(struct Curl_multi *multi);
|
||||
void Curl_cpool_multi_perform(struct Curl_multi *multi);
|
||||
|
||||
void Curl_cpool_multi_socket(struct Curl_multi *multi,
|
||||
curl_socket_t s, int ev_bitmask);
|
||||
|
||||
void Curl_conncache_multi_socket(struct Curl_multi *multi,
|
||||
curl_socket_t s, int ev_bitmask);
|
||||
void Curl_conncache_multi_close_all(struct Curl_multi *multi);
|
||||
|
||||
#endif /* HEADER_CURL_CONNCACHE_H */
|
||||
|
||||
+49
-95
@@ -208,31 +208,6 @@ bool Curl_shutdown_started(struct Curl_easy *data, int sockindex)
|
||||
return (pt->tv_sec > 0) || (pt->tv_usec > 0);
|
||||
}
|
||||
|
||||
/* Copies connection info into the transfer handle to make it available when
|
||||
the transfer handle is no longer associated with the connection. */
|
||||
void Curl_persistconninfo(struct Curl_easy *data, struct connectdata *conn,
|
||||
struct ip_quadruple *ip)
|
||||
{
|
||||
if(ip)
|
||||
data->info.primary = *ip;
|
||||
else {
|
||||
memset(&data->info.primary, 0, sizeof(data->info.primary));
|
||||
data->info.primary.remote_port = -1;
|
||||
data->info.primary.local_port = -1;
|
||||
}
|
||||
data->info.conn_scheme = conn->handler->scheme;
|
||||
/* conn_protocol can only provide "old" protocols */
|
||||
data->info.conn_protocol = (conn->handler->protocol) & CURLPROTO_MASK;
|
||||
data->info.conn_remote_port = conn->remote_port;
|
||||
data->info.used_proxy =
|
||||
#ifdef CURL_DISABLE_PROXY
|
||||
0
|
||||
#else
|
||||
conn->bits.proxy
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
static const struct Curl_addrinfo *
|
||||
addr_first_match(const struct Curl_addrinfo *addr, int family)
|
||||
{
|
||||
@@ -312,23 +287,6 @@ bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
struct connfind {
|
||||
curl_off_t id_tofind;
|
||||
struct connectdata *found;
|
||||
};
|
||||
|
||||
static int conn_is_conn(struct Curl_easy *data,
|
||||
struct connectdata *conn, void *param)
|
||||
{
|
||||
struct connfind *f = (struct connfind *)param;
|
||||
(void)data;
|
||||
if(conn->connection_id == f->id_tofind) {
|
||||
f->found = conn;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Used to extract socket and connectdata struct for the most recent
|
||||
* transfer on the given Curl_easy.
|
||||
@@ -345,30 +303,19 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
|
||||
* - that is associated with a multi handle, and whose connection
|
||||
* was detached with CURLOPT_CONNECT_ONLY
|
||||
*/
|
||||
if((data->state.lastconnect_id != -1) && (data->multi_easy || data->multi)) {
|
||||
struct connectdata *c;
|
||||
struct connfind find;
|
||||
find.id_tofind = data->state.lastconnect_id;
|
||||
find.found = NULL;
|
||||
if(data->state.lastconnect_id != -1) {
|
||||
struct connectdata *conn;
|
||||
|
||||
Curl_conncache_foreach(data,
|
||||
data->share && (data->share->specifier
|
||||
& (1<< CURL_LOCK_DATA_CONNECT))?
|
||||
&data->share->conn_cache:
|
||||
data->multi_easy?
|
||||
&data->multi_easy->conn_cache:
|
||||
&data->multi->conn_cache, &find, conn_is_conn);
|
||||
|
||||
if(!find.found) {
|
||||
conn = Curl_cpool_get_conn(data, data->state.lastconnect_id);
|
||||
if(!conn) {
|
||||
data->state.lastconnect_id = -1;
|
||||
return CURL_SOCKET_BAD;
|
||||
}
|
||||
|
||||
c = find.found;
|
||||
if(connp)
|
||||
/* only store this if the caller cares for it */
|
||||
*connp = c;
|
||||
return c->sock[FIRSTSOCKET];
|
||||
*connp = conn;
|
||||
return conn->sock[FIRSTSOCKET];
|
||||
}
|
||||
return CURL_SOCKET_BAD;
|
||||
}
|
||||
@@ -600,9 +547,11 @@ static CURLcode baller_start_next(struct Curl_cfilter *cf,
|
||||
{
|
||||
if(cf->sockindex == FIRSTSOCKET) {
|
||||
baller_next_addr(baller);
|
||||
/* If we get inconclusive answers from the server(s), we make
|
||||
* a second iteration over the address list */
|
||||
if(!baller->addr && baller->inconclusive && !baller->rewinded)
|
||||
/* If we get inconclusive answers from the server(s), we start
|
||||
* again until this whole thing times out. This allows us to
|
||||
* connect to servers that are gracefully restarting and the
|
||||
* packet routing to the new instance has not happened yet (e.g. QUIC). */
|
||||
if(!baller->addr && baller->inconclusive)
|
||||
baller_rewind(baller);
|
||||
baller_start(cf, data, baller, timeoutms);
|
||||
}
|
||||
@@ -634,7 +583,7 @@ static CURLcode baller_connect(struct Curl_cfilter *cf,
|
||||
baller->is_done = TRUE;
|
||||
}
|
||||
else if(Curl_timediff(*now, baller->started) >= baller->timeoutms) {
|
||||
infof(data, "%s connect timeout after %" CURL_FORMAT_TIMEDIFF_T
|
||||
infof(data, "%s connect timeout after %" FMT_TIMEDIFF_T
|
||||
"ms, move on!", baller->name, baller->timeoutms);
|
||||
#if defined(ETIMEDOUT)
|
||||
baller->error = ETIMEDOUT;
|
||||
@@ -725,7 +674,7 @@ evaluate:
|
||||
/* Nothing connected, check the time before we might
|
||||
* start new ballers or return ok. */
|
||||
if((ongoing || not_started) && Curl_timeleft(data, &now, TRUE) < 0) {
|
||||
failf(data, "Connection timeout after %" CURL_FORMAT_CURL_OFF_T " ms",
|
||||
failf(data, "Connection timeout after %" FMT_OFF_T " ms",
|
||||
Curl_timediff(now, data->progress.t_startsingle));
|
||||
return CURLE_OPERATION_TIMEDOUT;
|
||||
}
|
||||
@@ -748,8 +697,7 @@ evaluate:
|
||||
CURL_TRC_CF(data, cf, "%s done", baller->name);
|
||||
}
|
||||
else {
|
||||
CURL_TRC_CF(data, cf, "%s starting (timeout=%"
|
||||
CURL_FORMAT_TIMEDIFF_T "ms)",
|
||||
CURL_TRC_CF(data, cf, "%s starting (timeout=%" FMT_TIMEDIFF_T "ms)",
|
||||
baller->name, baller->timeoutms);
|
||||
++ongoing;
|
||||
++added;
|
||||
@@ -794,7 +742,7 @@ evaluate:
|
||||
hostname = conn->host.name;
|
||||
|
||||
failf(data, "Failed to connect to %s port %u after "
|
||||
"%" CURL_FORMAT_TIMEDIFF_T " ms: %s",
|
||||
"%" FMT_TIMEDIFF_T " ms: %s",
|
||||
hostname, conn->primary.remote_port,
|
||||
Curl_timediff(now, data->progress.t_startsingle),
|
||||
curl_easy_strerror(result));
|
||||
@@ -821,9 +769,9 @@ static CURLcode start_connect(struct Curl_cfilter *cf,
|
||||
struct cf_he_ctx *ctx = cf->ctx;
|
||||
struct connectdata *conn = cf->conn;
|
||||
CURLcode result = CURLE_COULDNT_CONNECT;
|
||||
int ai_family0, ai_family1;
|
||||
int ai_family0 = 0, ai_family1 = 0;
|
||||
timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
|
||||
const struct Curl_addrinfo *addr0, *addr1;
|
||||
const struct Curl_addrinfo *addr0 = NULL, *addr1 = NULL;
|
||||
|
||||
if(timeout_ms < 0) {
|
||||
/* a precaution, no need to continue if time already is up */
|
||||
@@ -842,33 +790,33 @@ static CURLcode start_connect(struct Curl_cfilter *cf,
|
||||
* the 2 connect attempt ballers to try different families, if possible.
|
||||
*
|
||||
*/
|
||||
if(conn->ip_version == CURL_IPRESOLVE_WHATEVER) {
|
||||
/* any IP version is allowed */
|
||||
ai_family0 = remotehost->addr?
|
||||
remotehost->addr->ai_family : 0;
|
||||
if(conn->ip_version == CURL_IPRESOLVE_V6) {
|
||||
#ifdef USE_IPV6
|
||||
ai_family1 = ai_family0 == AF_INET6 ?
|
||||
AF_INET : AF_INET6;
|
||||
#else
|
||||
ai_family1 = AF_UNSPEC;
|
||||
ai_family0 = AF_INET6;
|
||||
addr0 = addr_first_match(remotehost->addr, ai_family0);
|
||||
#endif
|
||||
}
|
||||
else if(conn->ip_version == CURL_IPRESOLVE_V4) {
|
||||
ai_family0 = AF_INET;
|
||||
addr0 = addr_first_match(remotehost->addr, ai_family0);
|
||||
}
|
||||
else {
|
||||
/* only one IP version is allowed */
|
||||
ai_family0 = (conn->ip_version == CURL_IPRESOLVE_V4) ?
|
||||
AF_INET :
|
||||
/* no user preference, we try ipv6 always first when available */
|
||||
#ifdef USE_IPV6
|
||||
AF_INET6;
|
||||
#else
|
||||
AF_UNSPEC;
|
||||
ai_family0 = AF_INET6;
|
||||
addr0 = addr_first_match(remotehost->addr, ai_family0);
|
||||
#endif
|
||||
ai_family1 = AF_UNSPEC;
|
||||
/* next candidate is ipv4 */
|
||||
ai_family1 = AF_INET;
|
||||
addr1 = addr_first_match(remotehost->addr, ai_family1);
|
||||
/* no ip address families, probably AF_UNIX or something, use the
|
||||
* address family given to us */
|
||||
if(!addr1 && !addr0 && remotehost->addr) {
|
||||
ai_family0 = remotehost->addr->ai_family;
|
||||
addr0 = addr_first_match(remotehost->addr, ai_family0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the first address in the list that matches the family,
|
||||
* this might give NULL, if we do not have any matches. */
|
||||
addr0 = addr_first_match(remotehost->addr, ai_family0);
|
||||
addr1 = addr_first_match(remotehost->addr, ai_family1);
|
||||
if(!addr0 && addr1) {
|
||||
/* switch around, so a single baller always uses addr0 */
|
||||
addr0 = addr1;
|
||||
@@ -887,8 +835,7 @@ static CURLcode start_connect(struct Curl_cfilter *cf,
|
||||
timeout_ms, EXPIRE_DNS_PER_NAME);
|
||||
if(result)
|
||||
return result;
|
||||
CURL_TRC_CF(data, cf, "created %s (timeout %"
|
||||
CURL_FORMAT_TIMEDIFF_T "ms)",
|
||||
CURL_TRC_CF(data, cf, "created %s (timeout %" FMT_TIMEDIFF_T "ms)",
|
||||
ctx->baller[0]->name, ctx->baller[0]->timeoutms);
|
||||
if(addr1) {
|
||||
/* second one gets a delayed start */
|
||||
@@ -899,8 +846,7 @@ static CURLcode start_connect(struct Curl_cfilter *cf,
|
||||
timeout_ms, EXPIRE_DNS_PER_NAME2);
|
||||
if(result)
|
||||
return result;
|
||||
CURL_TRC_CF(data, cf, "created %s (timeout %"
|
||||
CURL_FORMAT_TIMEDIFF_T "ms)",
|
||||
CURL_TRC_CF(data, cf, "created %s (timeout %" FMT_TIMEDIFF_T "ms)",
|
||||
ctx->baller[1]->name, ctx->baller[1]->timeoutms);
|
||||
Curl_expire(data, data->set.happy_eyeballs_timeout,
|
||||
EXPIRE_HAPPY_EYEBALLS);
|
||||
@@ -1020,12 +966,20 @@ static CURLcode cf_he_connect(struct Curl_cfilter *cf,
|
||||
cf->next = ctx->winner->cf;
|
||||
ctx->winner->cf = NULL;
|
||||
cf_he_ctx_clear(cf, data);
|
||||
Curl_conn_cf_cntrl(cf->next, data, TRUE,
|
||||
CF_CTRL_CONN_INFO_UPDATE, 0, NULL);
|
||||
|
||||
if(cf->conn->handler->protocol & PROTO_FAMILY_SSH)
|
||||
Curl_pgrsTime(data, TIMER_APPCONNECT); /* we are connected already */
|
||||
Curl_verboseconnect(data, cf->conn, cf->sockindex);
|
||||
if(Curl_trc_cf_is_verbose(cf, data)) {
|
||||
struct ip_quadruple ipquad;
|
||||
int is_ipv6;
|
||||
if(!Curl_conn_cf_get_ip_info(cf->next, data, &is_ipv6, &ipquad)) {
|
||||
const char *host, *disphost;
|
||||
int port;
|
||||
cf->next->cft->get_host(cf->next, data, &host, &disphost, &port);
|
||||
CURL_TRC_CF(data, cf, "Connected to %s (%s) port %u",
|
||||
disphost, ipquad.remote_ip, ipquad.remote_port);
|
||||
}
|
||||
}
|
||||
data->info.numconnects++; /* to track the # of connections made */
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -72,9 +72,6 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
|
||||
bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen,
|
||||
char *addr, int *port);
|
||||
|
||||
void Curl_persistconninfo(struct Curl_easy *data, struct connectdata *conn,
|
||||
struct ip_quadruple *ip);
|
||||
|
||||
/*
|
||||
* Curl_conncontrol() marks the end of a connection/stream. The 'closeit'
|
||||
* argument specifies if it is the end of a connection or a stream.
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
#define GZIP_MAGIC_1 0x8b
|
||||
|
||||
/* gzip flag byte */
|
||||
#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
|
||||
#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 */
|
||||
@@ -909,18 +909,18 @@ static CURLcode error_do_write(struct Curl_easy *data,
|
||||
struct Curl_cwriter *writer, int type,
|
||||
const char *buf, size_t nbytes)
|
||||
{
|
||||
char all[256];
|
||||
(void)Curl_all_content_encodings(all, sizeof(all));
|
||||
|
||||
(void) writer;
|
||||
(void) buf;
|
||||
(void) nbytes;
|
||||
|
||||
if(!(type & CLIENTWRITE_BODY) || !nbytes)
|
||||
return Curl_cwriter_write(data, writer->next, type, buf, nbytes);
|
||||
|
||||
failf(data, "Unrecognized content encoding type. "
|
||||
"libcurl understands %s content encodings.", all);
|
||||
else {
|
||||
char all[256];
|
||||
(void)Curl_all_content_encodings(all, sizeof(all));
|
||||
failf(data, "Unrecognized content encoding type. "
|
||||
"libcurl understands %s content encodings.", all);
|
||||
}
|
||||
return CURLE_BAD_CONTENT_ENCODING;
|
||||
}
|
||||
|
||||
|
||||
+7
-2
@@ -1028,6 +1028,8 @@ Curl_cookie_add(struct Curl_easy *data,
|
||||
* must also check that the data handle is not NULL since the psl code will
|
||||
* dereference it.
|
||||
*/
|
||||
DEBUGF(infof(data, "PSL check set-cookie '%s' for domain=%s in %s",
|
||||
co->name, co->domain, domain));
|
||||
if(data && (domain && co->domain && !Curl_host_is_ipnum(co->domain))) {
|
||||
bool acceptable = FALSE;
|
||||
char lcase[256];
|
||||
@@ -1054,6 +1056,9 @@ Curl_cookie_add(struct Curl_easy *data,
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#else
|
||||
DEBUGF(infof(data, "NO PSL to check set-cookie '%s' for domain=%s in %s",
|
||||
co->name, co->domain, domain));
|
||||
#endif
|
||||
|
||||
/* A non-secure cookie may not overlay an existing secure cookie. */
|
||||
@@ -1165,7 +1170,7 @@ Curl_cookie_add(struct Curl_easy *data,
|
||||
if(c->running)
|
||||
/* Only show this when NOT reading the cookies from a file */
|
||||
infof(data, "%s cookie %s=\"%s\" for domain %s, path %s, "
|
||||
"expire %" CURL_FORMAT_CURL_OFF_T,
|
||||
"expire %" FMT_OFF_T,
|
||||
replace_old?"Replaced":"Added", co->name, co->value,
|
||||
co->domain, co->path, co->expires);
|
||||
|
||||
@@ -1584,7 +1589,7 @@ static char *get_netscape_format(const struct Cookie *co)
|
||||
"%s\t" /* tailmatch */
|
||||
"%s\t" /* path */
|
||||
"%s\t" /* secure */
|
||||
"%" CURL_FORMAT_CURL_OFF_T "\t" /* expires */
|
||||
"%" FMT_OFF_T "\t" /* expires */
|
||||
"%s\t" /* name */
|
||||
"%s", /* value */
|
||||
co->httponly?"#HttpOnly_":"",
|
||||
|
||||
+1
-1
@@ -571,7 +571,7 @@ curl_dbg_getaddrinfo(const char *hostname,
|
||||
|
||||
#if defined(HAVE_GETADDRINFO) && defined(USE_RESOLVE_ON_IPS)
|
||||
/*
|
||||
* Work-arounds the sin6_port is always zero bug on iOS 9.3.2 and Mac OS X
|
||||
* Work-arounds the sin6_port is always zero bug on iOS 9.3.2 and macOS
|
||||
* 10.11.5.
|
||||
*/
|
||||
void Curl_addrinfo_set_port(struct Curl_addrinfo *addrinfo, int port)
|
||||
|
||||
+22
-12
@@ -89,6 +89,9 @@
|
||||
/* disables HTTP */
|
||||
#cmakedefine CURL_DISABLE_HTTP 1
|
||||
|
||||
/* disabled all HTTP authentication methods */
|
||||
#cmakedefine CURL_DISABLE_HTTP_AUTH 1
|
||||
|
||||
/* disables IMAP */
|
||||
#cmakedefine CURL_DISABLE_IMAP 1
|
||||
|
||||
@@ -131,6 +134,12 @@
|
||||
/* disables RTSP */
|
||||
#cmakedefine CURL_DISABLE_RTSP 1
|
||||
|
||||
/* disables SHA-512/256 hash algorithm */
|
||||
#cmakedefine CURL_DISABLE_SHA512_256 1
|
||||
|
||||
/* disabled shuffle DNS feature */
|
||||
#cmakedefine CURL_DISABLE_SHUFFLE_DNS 1
|
||||
|
||||
/* disables SMB */
|
||||
#cmakedefine CURL_DISABLE_SMB 1
|
||||
|
||||
@@ -304,9 +313,6 @@
|
||||
/* if you have the GNU gssapi libraries */
|
||||
#cmakedefine HAVE_GSSGNU 1
|
||||
|
||||
/* Define to 1 if you have the `idna_strerror' function. */
|
||||
#cmakedefine HAVE_IDNA_STRERROR 1
|
||||
|
||||
/* Define to 1 if you have the <ifaddrs.h> header file. */
|
||||
#cmakedefine HAVE_IFADDRS_H 1
|
||||
|
||||
@@ -632,9 +638,6 @@
|
||||
/* Define to the version of this package. */
|
||||
#cmakedefine PACKAGE_VERSION ${PACKAGE_VERSION}
|
||||
|
||||
/* a suitable file to read random data from */
|
||||
#cmakedefine RANDOM_FILE "${RANDOM_FILE}"
|
||||
|
||||
/*
|
||||
Note: SIZEOF_* variables are fetched with CMake through check_type_size().
|
||||
As per CMake documentation on CheckTypeSize, C preprocessor code is
|
||||
@@ -677,7 +680,7 @@ ${SIZEOF_TIME_T_CODE}
|
||||
/* Define if you want to enable POSIX threaded DNS lookup */
|
||||
#cmakedefine USE_THREADS_POSIX 1
|
||||
|
||||
/* Define if you want to enable WIN32 threaded DNS lookup */
|
||||
/* Define if you want to enable Win32 threaded DNS lookup */
|
||||
#cmakedefine USE_THREADS_WIN32 1
|
||||
|
||||
/* if GnuTLS is enabled */
|
||||
@@ -692,6 +695,9 @@ ${SIZEOF_TIME_T_CODE}
|
||||
/* if BearSSL is enabled */
|
||||
#cmakedefine USE_BEARSSL 1
|
||||
|
||||
/* if Rustls is enabled */
|
||||
#cmakedefine USE_RUSTLS 1
|
||||
|
||||
/* if wolfSSL is enabled */
|
||||
#cmakedefine USE_WOLFSSL 1
|
||||
|
||||
@@ -707,6 +713,9 @@ ${SIZEOF_TIME_T_CODE}
|
||||
/* if libssh2 is in use */
|
||||
#cmakedefine USE_LIBSSH2 1
|
||||
|
||||
/* if wolfssh is in use */
|
||||
#cmakedefine USE_WOLFSSH 1
|
||||
|
||||
/* if libpsl is in use */
|
||||
#cmakedefine USE_LIBPSL 1
|
||||
|
||||
@@ -722,6 +731,12 @@ ${SIZEOF_TIME_T_CODE}
|
||||
/* if GSASL is in use */
|
||||
#cmakedefine USE_GSASL 1
|
||||
|
||||
/* if libuv is in use */
|
||||
#cmakedefine USE_LIBUV 1
|
||||
|
||||
/* Define to 1 if you have the <uv.h> header file. */
|
||||
#cmakedefine HAVE_UV_H 1
|
||||
|
||||
/* Define to 1 if you do not want the OpenSSL configuration to be loaded
|
||||
automatically */
|
||||
#cmakedefine CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG 1
|
||||
@@ -765,11 +780,6 @@ ${SIZEOF_TIME_T_CODE}
|
||||
/* Version number of package */
|
||||
#cmakedefine VERSION ${VERSION}
|
||||
|
||||
/* Define to 1 if OS is AIX. */
|
||||
#ifndef _ALL_SOURCE
|
||||
# undef _ALL_SOURCE
|
||||
#endif
|
||||
|
||||
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||
#cmakedefine _FILE_OFFSET_BITS ${_FILE_OFFSET_BITS}
|
||||
|
||||
|
||||
+4
-4
@@ -24,10 +24,10 @@
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#if defined(USE_CURL_NTLM_CORE) && !defined(USE_WOLFSSL) && \
|
||||
(defined(USE_GNUTLS) || \
|
||||
defined(USE_SECTRANSP) || \
|
||||
defined(USE_OS400CRYPTO) || \
|
||||
#if defined(USE_CURL_NTLM_CORE) && \
|
||||
(defined(USE_GNUTLS) || \
|
||||
defined(USE_SECTRANSP) || \
|
||||
defined(USE_OS400CRYPTO) || \
|
||||
defined(USE_WIN32_CRYPTO))
|
||||
|
||||
#include "curl_des.h"
|
||||
|
||||
+4
-4
@@ -26,10 +26,10 @@
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#if defined(USE_CURL_NTLM_CORE) && !defined(USE_WOLFSSL) && \
|
||||
(defined(USE_GNUTLS) || \
|
||||
defined(USE_SECTRANSP) || \
|
||||
defined(USE_OS400CRYPTO) || \
|
||||
#if defined(USE_CURL_NTLM_CORE) && \
|
||||
(defined(USE_GNUTLS) || \
|
||||
defined(USE_SECTRANSP) || \
|
||||
defined(USE_OS400CRYPTO) || \
|
||||
defined(USE_WIN32_CRYPTO))
|
||||
|
||||
/* Applies odd parity to the given byte array */
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
/* default pattern matching function
|
||||
* =================================
|
||||
* Implemented with recursive backtracking, if you want to use Curl_fnmatch,
|
||||
* please note that there is not implemented UTF/UNICODE support.
|
||||
* please note that there is not implemented UTF/Unicode support.
|
||||
*
|
||||
* Implemented features:
|
||||
* '?' notation, does not match UTF characters
|
||||
|
||||
+4
-13
@@ -39,15 +39,6 @@
|
||||
*
|
||||
* Note: The function always returns the un-qualified hostname rather
|
||||
* than being provider dependent.
|
||||
*
|
||||
* For libcurl shared library release builds the test suite preloads
|
||||
* another shared library named libhostname using the LD_PRELOAD
|
||||
* mechanism which intercepts, and might override, the gethostname()
|
||||
* function call. In this case a given platform must support the
|
||||
* LD_PRELOAD mechanism and additionally have environment variable
|
||||
* CURL_GETHOSTNAME set in order to override the returned hostname.
|
||||
*
|
||||
* For libcurl static library release builds no overriding takes place.
|
||||
*/
|
||||
|
||||
int Curl_gethostname(char * const name, GETHOSTNAME_TYPE_ARG2 namelen)
|
||||
@@ -68,7 +59,10 @@ int Curl_gethostname(char * const name, GETHOSTNAME_TYPE_ARG2 namelen)
|
||||
/* Override hostname when environment variable CURL_GETHOSTNAME is set */
|
||||
const char *force_hostname = getenv("CURL_GETHOSTNAME");
|
||||
if(force_hostname) {
|
||||
strncpy(name, force_hostname, namelen - 1);
|
||||
if(strlen(force_hostname) < (size_t)namelen)
|
||||
strcpy(name, force_hostname);
|
||||
else
|
||||
return 1; /* can't do it */
|
||||
err = 0;
|
||||
}
|
||||
else {
|
||||
@@ -78,9 +72,6 @@ int Curl_gethostname(char * const name, GETHOSTNAME_TYPE_ARG2 namelen)
|
||||
|
||||
#else /* DEBUGBUILD */
|
||||
|
||||
/* The call to system's gethostname() might get intercepted by the
|
||||
libhostname library when libcurl is built as a non-debug shared
|
||||
library when running the test suite. */
|
||||
name[0] = '\0';
|
||||
err = gethostname(name, namelen);
|
||||
|
||||
|
||||
@@ -33,6 +33,9 @@
|
||||
#include "memdebug.h"
|
||||
|
||||
#ifndef HAVE_MEMRCHR
|
||||
#if (!defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)) || \
|
||||
defined(USE_OPENSSL) || \
|
||||
defined(USE_SCHANNEL)
|
||||
|
||||
/*
|
||||
* Curl_memrchr()
|
||||
@@ -61,4 +64,5 @@ Curl_memrchr(const void *s, int c, size_t n)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* HAVE_MEMRCHR */
|
||||
|
||||
@@ -34,11 +34,15 @@
|
||||
#endif
|
||||
|
||||
#else /* HAVE_MEMRCHR */
|
||||
#if (!defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)) || \
|
||||
defined(USE_OPENSSL) || \
|
||||
defined(USE_SCHANNEL)
|
||||
|
||||
void *Curl_memrchr(const void *s, int c, size_t n);
|
||||
|
||||
#define memrchr(x,y,z) Curl_memrchr((x),(y),(z))
|
||||
|
||||
#endif
|
||||
#endif /* HAVE_MEMRCHR */
|
||||
|
||||
#endif /* HEADER_CURL_MEMRCHR_H */
|
||||
|
||||
@@ -39,12 +39,12 @@ char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w);
|
||||
* Macros curlx_convert_UTF8_to_tchar(), curlx_convert_tchar_to_UTF8()
|
||||
* and curlx_unicodefree() main purpose is to minimize the number of
|
||||
* preprocessor conditional directives needed by code using these
|
||||
* to differentiate UNICODE from non-UNICODE builds.
|
||||
* to differentiate Unicode from non-Unicode builds.
|
||||
*
|
||||
* In the case of a non-UNICODE build the tchar strings are char strings that
|
||||
* In the case of a non-Unicode build the tchar strings are char strings that
|
||||
* are duplicated via strdup and remain in whatever the passed in encoding is,
|
||||
* which is assumed to be UTF-8 but may be other encoding. Therefore the
|
||||
* significance of the conversion functions is primarily for UNICODE builds.
|
||||
* significance of the conversion functions is primarily for Unicode builds.
|
||||
*
|
||||
* Allocated memory should be free'd with curlx_unicodefree().
|
||||
*
|
||||
|
||||
+15
-11
@@ -57,9 +57,14 @@
|
||||
#if !defined(OPENSSL_NO_DES) && !defined(OPENSSL_NO_DEPRECATED_3_0)
|
||||
#define USE_OPENSSL_DES
|
||||
#endif
|
||||
#elif defined(USE_WOLFSSL)
|
||||
#include <wolfssl/options.h>
|
||||
#if !defined(NO_DES3)
|
||||
#define USE_OPENSSL_DES
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(USE_OPENSSL_DES) || defined(USE_WOLFSSL)
|
||||
#if defined(USE_OPENSSL_DES)
|
||||
|
||||
#if defined(USE_OPENSSL)
|
||||
# include <openssl/des.h>
|
||||
@@ -67,7 +72,6 @@
|
||||
# include <openssl/ssl.h>
|
||||
# include <openssl/rand.h>
|
||||
#else
|
||||
# include <wolfssl/options.h>
|
||||
# include <wolfssl/openssl/des.h>
|
||||
# include <wolfssl/openssl/md5.h>
|
||||
# include <wolfssl/openssl/ssl.h>
|
||||
@@ -148,7 +152,7 @@ static void extend_key_56_to_64(const unsigned char *key_56, char *key)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(USE_OPENSSL_DES) || defined(USE_WOLFSSL)
|
||||
#if defined(USE_OPENSSL_DES)
|
||||
/*
|
||||
* Turns a 56-bit key into a 64-bit, odd parity key and sets the key. The
|
||||
* key schedule ks is also set.
|
||||
@@ -313,7 +317,7 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys,
|
||||
const unsigned char *plaintext,
|
||||
unsigned char *results)
|
||||
{
|
||||
#if defined(USE_OPENSSL_DES) || defined(USE_WOLFSSL)
|
||||
#if defined(USE_OPENSSL_DES)
|
||||
DES_key_schedule ks;
|
||||
|
||||
setup_des_key(keys, DESKEY(ks));
|
||||
@@ -367,7 +371,7 @@ CURLcode Curl_ntlm_core_mk_lm_hash(const char *password,
|
||||
{
|
||||
/* Create LanManager hashed password. */
|
||||
|
||||
#if defined(USE_OPENSSL_DES) || defined(USE_WOLFSSL)
|
||||
#if defined(USE_OPENSSL_DES)
|
||||
DES_key_schedule ks;
|
||||
|
||||
setup_des_key(pw, DESKEY(ks));
|
||||
@@ -534,13 +538,13 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen,
|
||||
/*
|
||||
* Curl_ntlm_core_mk_ntlmv2_resp()
|
||||
*
|
||||
* This creates the NTLMv2 response as set in the ntlm type-3 message.
|
||||
* This creates the NTLMv2 response as set in the NTLM type-3 message.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* ntlmv2hash [in] - The ntlmv2 hash (16 bytes)
|
||||
* ntlmv2hash [in] - The NTLMv2 hash (16 bytes)
|
||||
* challenge_client [in] - The client nonce (8 bytes)
|
||||
* ntlm [in] - The ntlm data struct being used to read TargetInfo
|
||||
* ntlm [in] - The NTLM data struct being used to read TargetInfo
|
||||
and Server challenge received in the type-2 message
|
||||
* ntresp [out] - The address where a pointer to newly allocated
|
||||
* memory holding the NTLMv2 response.
|
||||
@@ -629,11 +633,11 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
|
||||
/*
|
||||
* Curl_ntlm_core_mk_lmv2_resp()
|
||||
*
|
||||
* This creates the LMv2 response as used in the ntlm type-3 message.
|
||||
* This creates the LMv2 response as used in the NTLM type-3 message.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* ntlmv2hash [in] - The ntlmv2 hash (16 bytes)
|
||||
* ntlmv2hash [in] - The NTLMv2 hash (16 bytes)
|
||||
* challenge_client [in] - The client nonce (8 bytes)
|
||||
* challenge_client [in] - The server challenge (8 bytes)
|
||||
* lmresp [out] - The LMv2 response (24 bytes)
|
||||
@@ -657,7 +661,7 @@ CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash,
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
/* Concatenate the HMAC MD5 output with the client nonce */
|
||||
/* Concatenate the HMAC MD5 output with the client nonce */
|
||||
memcpy(lmresp, hmac_output, 16);
|
||||
memcpy(lmresp + 16, challenge_client, 8);
|
||||
|
||||
|
||||
+4
-1
@@ -29,6 +29,10 @@
|
||||
* *rintf() functions.
|
||||
*/
|
||||
|
||||
#ifndef CURL_TEMP_PRINTF
|
||||
#error "CURL_TEMP_PRINTF must be set before including curl/mprintf.h"
|
||||
#endif
|
||||
|
||||
#include <curl/mprintf.h>
|
||||
|
||||
#define MERR_OK 0
|
||||
@@ -40,7 +44,6 @@
|
||||
# undef msnprintf
|
||||
# undef vprintf
|
||||
# undef vfprintf
|
||||
# undef vsnprintf
|
||||
# undef mvsnprintf
|
||||
# undef aprintf
|
||||
# undef vaprintf
|
||||
|
||||
+6
-9
@@ -55,15 +55,13 @@ CURLcode Curl_range(struct Curl_easy *data)
|
||||
if((to_t == CURL_OFFT_INVAL) && !from_t) {
|
||||
/* X - */
|
||||
data->state.resume_from = from;
|
||||
DEBUGF(infof(data, "RANGE %" CURL_FORMAT_CURL_OFF_T " to end of file",
|
||||
from));
|
||||
DEBUGF(infof(data, "RANGE %" FMT_OFF_T " to end of file", from));
|
||||
}
|
||||
else if((from_t == CURL_OFFT_INVAL) && !to_t) {
|
||||
/* -Y */
|
||||
data->req.maxdownload = to;
|
||||
data->state.resume_from = -to;
|
||||
DEBUGF(infof(data, "RANGE the last %" CURL_FORMAT_CURL_OFF_T " bytes",
|
||||
to));
|
||||
DEBUGF(infof(data, "RANGE the last %" FMT_OFF_T " bytes", to));
|
||||
}
|
||||
else {
|
||||
/* X-Y */
|
||||
@@ -79,13 +77,12 @@ CURLcode Curl_range(struct Curl_easy *data)
|
||||
|
||||
data->req.maxdownload = totalsize + 1; /* include last byte */
|
||||
data->state.resume_from = from;
|
||||
DEBUGF(infof(data, "RANGE from %" CURL_FORMAT_CURL_OFF_T
|
||||
" getting %" CURL_FORMAT_CURL_OFF_T " bytes",
|
||||
DEBUGF(infof(data, "RANGE from %" FMT_OFF_T
|
||||
" getting %" FMT_OFF_T " bytes",
|
||||
from, data->req.maxdownload));
|
||||
}
|
||||
DEBUGF(infof(data, "range-download from %" CURL_FORMAT_CURL_OFF_T
|
||||
" to %" CURL_FORMAT_CURL_OFF_T ", totally %"
|
||||
CURL_FORMAT_CURL_OFF_T " bytes",
|
||||
DEBUGF(infof(data, "range-download from %" FMT_OFF_T
|
||||
" to %" FMT_OFF_T ", totally %" FMT_OFF_T " bytes",
|
||||
from, to, data->req.maxdownload));
|
||||
}
|
||||
else
|
||||
|
||||
+2
-1
@@ -329,13 +329,14 @@ static ssize_t rtmp_recv(struct Curl_easy *data, int sockindex, char *buf,
|
||||
}
|
||||
|
||||
static ssize_t rtmp_send(struct Curl_easy *data, int sockindex,
|
||||
const void *buf, size_t len, CURLcode *err)
|
||||
const void *buf, size_t len, bool eos, CURLcode *err)
|
||||
{
|
||||
struct connectdata *conn = data->conn;
|
||||
RTMP *r = conn->proto.rtmp;
|
||||
ssize_t num;
|
||||
|
||||
(void)sockindex; /* unused */
|
||||
(void)eos; /* unused */
|
||||
|
||||
num = RTMP_Write(r, (char *)buf, curlx_uztosi(len));
|
||||
if(num < 0)
|
||||
|
||||
+24
-10
@@ -28,6 +28,9 @@
|
||||
#define CURL_NO_OLDIES
|
||||
#endif
|
||||
|
||||
/* 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)
|
||||
#ifdef __GNUC__
|
||||
@@ -319,7 +322,7 @@
|
||||
|
||||
/* curl uses its own printf() function internally. It understands the GNU
|
||||
* format. Use this format, so that is matches the GNU format attribute we
|
||||
* use with the mingw compiler, allowing it to verify them at compile-time.
|
||||
* use with the MinGW compiler, allowing it to verify them at compile-time.
|
||||
*/
|
||||
#ifdef __MINGW32__
|
||||
# undef CURL_FORMAT_CURL_OFF_T
|
||||
@@ -345,6 +348,9 @@
|
||||
#define CURL_PRINTF(fmt, arg)
|
||||
#endif
|
||||
|
||||
/* Override default printf mask check rules in "curl/mprintf.h" */
|
||||
#define CURL_TEMP_PRINTF CURL_PRINTF
|
||||
|
||||
/* Workaround for mainline llvm v16 and earlier missing a built-in macro
|
||||
expected by macOS SDK v14 / Xcode v15 (2023) and newer.
|
||||
gcc (as of v14) is also missing it. */
|
||||
@@ -444,7 +450,7 @@
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Large file (>2Gb) support using WIN32 functions.
|
||||
* Large file (>2Gb) support using Win32 functions.
|
||||
*/
|
||||
|
||||
#ifdef USE_WIN32_LARGE_FILES
|
||||
@@ -467,7 +473,7 @@
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Small file (<2Gb) support using WIN32 functions.
|
||||
* Small file (<2Gb) support using Win32 functions.
|
||||
*/
|
||||
|
||||
#ifdef USE_WIN32_SMALL_FILES
|
||||
@@ -513,11 +519,11 @@
|
||||
#endif
|
||||
|
||||
#if SIZEOF_CURL_SOCKET_T < 8
|
||||
# define CURL_FORMAT_SOCKET_T "d"
|
||||
# define FMT_SOCKET_T "d"
|
||||
#elif defined(__MINGW32__)
|
||||
# define CURL_FORMAT_SOCKET_T "zd"
|
||||
# define FMT_SOCKET_T "zd"
|
||||
#else
|
||||
# define CURL_FORMAT_SOCKET_T "qd"
|
||||
# define FMT_SOCKET_T "qd"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -565,10 +571,13 @@
|
||||
# endif
|
||||
# define CURL_UINT64_SUFFIX CURL_SUFFIX_CURL_OFF_TU
|
||||
# define CURL_UINT64_C(val) CURL_CONC_MACROS(val,CURL_UINT64_SUFFIX)
|
||||
# define CURL_PRId64 CURL_FORMAT_CURL_OFF_T
|
||||
# define CURL_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
|
||||
#define FMT_OFF_TU CURL_FORMAT_CURL_OFF_TU
|
||||
|
||||
#if (SIZEOF_TIME_T == 4)
|
||||
# ifdef HAVE_TIME_T_UNSIGNED
|
||||
# define TIME_T_MAX UINT_MAX
|
||||
@@ -715,6 +724,11 @@
|
||||
#define USE_SSL /* SSL support has been enabled */
|
||||
#endif
|
||||
|
||||
#if defined(USE_WOLFSSL) && defined(USE_GNUTLS)
|
||||
/* Avoid defining unprefixed wolfSSL SHA macros colliding with nettle ones */
|
||||
#define NO_OLD_WC_NAMES
|
||||
#endif
|
||||
|
||||
/* Single point where USE_SPNEGO definition might be defined */
|
||||
#if !defined(CURL_DISABLE_NEGOTIATE_AUTH) && \
|
||||
(defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI))
|
||||
@@ -816,7 +830,7 @@
|
||||
|
||||
#if defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H)
|
||||
# if defined(SOCKET) || defined(USE_WINSOCK)
|
||||
# error "WinSock and lwIP TCP/IP stack definitions shall not coexist!"
|
||||
# error "Winsock and lwIP TCP/IP stack definitions shall not coexist!"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
@@ -854,7 +868,7 @@ Therefore we specify it explicitly. https://github.com/curl/curl/pull/258
|
||||
#define FOPEN_WRITETEXT "wt"
|
||||
#define FOPEN_APPENDTEXT "at"
|
||||
#elif defined(__CYGWIN__)
|
||||
/* Cygwin has specific behavior we need to address when WIN32 is not defined.
|
||||
/* Cygwin has specific behavior we need to address when _WIN32 is not defined.
|
||||
https://cygwin.com/cygwin-ug-net/using-textbinary.html
|
||||
For write we want our output to have line endings of LF and be compatible with
|
||||
other Cygwin utilities. For read we want to handle input that may have line
|
||||
|
||||
+2
-7
@@ -33,13 +33,8 @@
|
||||
|
||||
extern const struct HMAC_params Curl_HMAC_SHA256[1];
|
||||
|
||||
#ifdef USE_WOLFSSL
|
||||
/* SHA256_DIGEST_LENGTH is an enum value in wolfSSL. Need to import it from
|
||||
* sha.h */
|
||||
#include <wolfssl/options.h>
|
||||
#include <wolfssl/openssl/sha.h>
|
||||
#else
|
||||
#define SHA256_DIGEST_LENGTH 32
|
||||
#ifndef CURL_SHA256_DIGEST_LENGTH
|
||||
#define CURL_SHA256_DIGEST_LENGTH 32 /* fixed size */
|
||||
#endif
|
||||
|
||||
CURLcode Curl_sha256it(unsigned char *outbuffer, const unsigned char *input,
|
||||
|
||||
+41
-34
@@ -37,7 +37,7 @@
|
||||
* * SecureTransport (Darwin)
|
||||
* * mbedTLS
|
||||
* * BearSSL
|
||||
* * rustls
|
||||
* * Rustls
|
||||
* Skip the backend if it does not support the required algorithm */
|
||||
|
||||
#if defined(USE_OPENSSL)
|
||||
@@ -93,13 +93,13 @@
|
||||
/**
|
||||
* Size of the SHA-512/256 single processing block in bytes.
|
||||
*/
|
||||
#define SHA512_256_BLOCK_SIZE 128
|
||||
#define CURL_SHA512_256_BLOCK_SIZE 128
|
||||
|
||||
/**
|
||||
* Size of the SHA-512/256 resulting digest in bytes.
|
||||
* This is the final digest size, not intermediate hash.
|
||||
*/
|
||||
#define SHA512_256_DIGEST_SIZE SHA512_256_DIGEST_LENGTH
|
||||
#define CURL_SHA512_256_DIGEST_SIZE CURL_SHA512_256_DIGEST_LENGTH
|
||||
|
||||
/**
|
||||
* Context type used for SHA-512/256 calculations
|
||||
@@ -124,9 +124,9 @@ Curl_sha512_256_init(void *context)
|
||||
|
||||
if(EVP_DigestInit_ex(*ctx, EVP_sha512_256(), NULL)) {
|
||||
/* Check whether the header and this file use the same numbers */
|
||||
DEBUGASSERT(EVP_MD_CTX_size(*ctx) == SHA512_256_DIGEST_SIZE);
|
||||
DEBUGASSERT(EVP_MD_CTX_size(*ctx) == CURL_SHA512_256_DIGEST_SIZE);
|
||||
/* Check whether the block size is correct */
|
||||
DEBUGASSERT(EVP_MD_CTX_block_size(*ctx) == SHA512_256_BLOCK_SIZE);
|
||||
DEBUGASSERT(EVP_MD_CTX_block_size(*ctx) == CURL_SHA512_256_BLOCK_SIZE);
|
||||
|
||||
return CURLE_OK; /* Success */
|
||||
}
|
||||
@@ -163,7 +163,8 @@ Curl_sha512_256_update(void *context,
|
||||
* Finalise SHA-512/256 calculation, return digest.
|
||||
*
|
||||
* @param context the calculation context
|
||||
* @param[out] digest set to the hash, must be #SHA512_256_DIGEST_SIZE bytes
|
||||
* @param[out] digest set to the hash, must be #CURL_SHA512_256_DIGEST_SIZE
|
||||
# bytes
|
||||
* @return CURLE_OK if succeed,
|
||||
* error code otherwise
|
||||
*/
|
||||
@@ -177,11 +178,11 @@ Curl_sha512_256_finish(unsigned char *digest,
|
||||
#ifdef NEED_NETBSD_SHA512_256_WORKAROUND
|
||||
/* Use a larger buffer to work around a bug in NetBSD:
|
||||
https://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=58039 */
|
||||
unsigned char tmp_digest[SHA512_256_DIGEST_SIZE * 2];
|
||||
unsigned char tmp_digest[CURL_SHA512_256_DIGEST_SIZE * 2];
|
||||
ret = EVP_DigestFinal_ex(*ctx,
|
||||
tmp_digest, NULL) ? CURLE_OK : CURLE_SSL_CIPHER;
|
||||
if(ret == CURLE_OK)
|
||||
memcpy(digest, tmp_digest, SHA512_256_DIGEST_SIZE);
|
||||
memcpy(digest, tmp_digest, CURL_SHA512_256_DIGEST_SIZE);
|
||||
explicit_memset(tmp_digest, 0, sizeof(tmp_digest));
|
||||
#else /* ! NEED_NETBSD_SHA512_256_WORKAROUND */
|
||||
ret = EVP_DigestFinal_ex(*ctx, digest, NULL) ? CURLE_OK : CURLE_SSL_CIPHER;
|
||||
@@ -195,6 +196,9 @@ Curl_sha512_256_finish(unsigned char *digest,
|
||||
|
||||
#elif defined(USE_GNUTLS_SHA512_256)
|
||||
|
||||
#define CURL_SHA512_256_BLOCK_SIZE SHA512_256_BLOCK_SIZE
|
||||
#define CURL_SHA512_256_DIGEST_SIZE SHA512_256_DIGEST_SIZE
|
||||
|
||||
/**
|
||||
* Context type used for SHA-512/256 calculations
|
||||
*/
|
||||
@@ -212,7 +216,7 @@ Curl_sha512_256_init(void *context)
|
||||
Curl_sha512_256_ctx *const ctx = (Curl_sha512_256_ctx *)context;
|
||||
|
||||
/* Check whether the header and this file use the same numbers */
|
||||
DEBUGASSERT(SHA512_256_DIGEST_LENGTH == SHA512_256_DIGEST_SIZE);
|
||||
DEBUGASSERT(CURL_SHA512_256_DIGEST_LENGTH == CURL_SHA512_256_DIGEST_SIZE);
|
||||
|
||||
sha512_256_init(ctx);
|
||||
|
||||
@@ -247,7 +251,8 @@ Curl_sha512_256_update(void *context,
|
||||
* Finalise SHA-512/256 calculation, return digest.
|
||||
*
|
||||
* @param context the calculation context
|
||||
* @param[out] digest set to the hash, must be #SHA512_256_DIGEST_SIZE bytes
|
||||
* @param[out] digest set to the hash, must be #CURL_SHA512_256_DIGEST_SIZE
|
||||
# bytes
|
||||
* @return always CURLE_OK
|
||||
*/
|
||||
static CURLcode
|
||||
@@ -256,7 +261,8 @@ Curl_sha512_256_finish(unsigned char *digest,
|
||||
{
|
||||
Curl_sha512_256_ctx *const ctx = (Curl_sha512_256_ctx *)context;
|
||||
|
||||
sha512_256_digest(ctx, (size_t)SHA512_256_DIGEST_SIZE, (uint8_t *)digest);
|
||||
sha512_256_digest(ctx,
|
||||
(size_t)CURL_SHA512_256_DIGEST_SIZE, (uint8_t *)digest);
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
@@ -360,7 +366,7 @@ MHDx_rotr64(curl_uint64_t value, unsigned int bits)
|
||||
* Size of the SHA-512/256 resulting digest in bytes
|
||||
* This is the final digest size, not intermediate hash.
|
||||
*/
|
||||
#define SHA512_256_DIGEST_SIZE \
|
||||
#define CURL_SHA512_256_DIGEST_SIZE \
|
||||
(SHA512_256_DIGEST_SIZE_WORDS * SHA512_256_BYTES_IN_WORD)
|
||||
|
||||
/**
|
||||
@@ -371,7 +377,7 @@ MHDx_rotr64(curl_uint64_t value, unsigned int bits)
|
||||
/**
|
||||
* Size of the SHA-512/256 single processing block in bytes.
|
||||
*/
|
||||
#define SHA512_256_BLOCK_SIZE (SHA512_256_BLOCK_SIZE_BITS / 8)
|
||||
#define CURL_SHA512_256_BLOCK_SIZE (SHA512_256_BLOCK_SIZE_BITS / 8)
|
||||
|
||||
/**
|
||||
* Size of the SHA-512/256 single processing block in words.
|
||||
@@ -425,7 +431,7 @@ MHDx_sha512_256_init(void *context)
|
||||
struct mhdx_sha512_256ctx *const ctx = (struct mhdx_sha512_256ctx *) context;
|
||||
|
||||
/* Check whether the header and this file use the same numbers */
|
||||
DEBUGASSERT(SHA512_256_DIGEST_LENGTH == SHA512_256_DIGEST_SIZE);
|
||||
DEBUGASSERT(CURL_SHA512_256_DIGEST_LENGTH == CURL_SHA512_256_DIGEST_SIZE);
|
||||
|
||||
DEBUGASSERT(sizeof(curl_uint64_t) == 8);
|
||||
|
||||
@@ -453,7 +459,7 @@ MHDx_sha512_256_init(void *context)
|
||||
* Base of the SHA-512/256 transformation.
|
||||
* Gets a full 128 bytes block of data and updates hash values;
|
||||
* @param H hash values
|
||||
* @param data the data buffer with #SHA512_256_BLOCK_SIZE bytes block
|
||||
* @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],
|
||||
@@ -636,9 +642,9 @@ MHDx_sha512_256_update(void *context,
|
||||
if(0 == length)
|
||||
return CURLE_OK; /* Shortcut, do nothing */
|
||||
|
||||
/* Note: (count & (SHA512_256_BLOCK_SIZE-1))
|
||||
equals (count % SHA512_256_BLOCK_SIZE) for this block size. */
|
||||
bytes_have = (unsigned int) (ctx->count & (SHA512_256_BLOCK_SIZE - 1));
|
||||
/* Note: (count & (CURL_SHA512_256_BLOCK_SIZE-1))
|
||||
equals (count % CURL_SHA512_256_BLOCK_SIZE) for this block size. */
|
||||
bytes_have = (unsigned int) (ctx->count & (CURL_SHA512_256_BLOCK_SIZE - 1));
|
||||
ctx->count += length;
|
||||
if(length > ctx->count)
|
||||
ctx->count_bits_hi += 1U << 3; /* Value wrap */
|
||||
@@ -646,7 +652,7 @@ MHDx_sha512_256_update(void *context,
|
||||
ctx->count &= CURL_UINT64_C(0x1FFFFFFFFFFFFFFF);
|
||||
|
||||
if(0 != bytes_have) {
|
||||
unsigned int bytes_left = SHA512_256_BLOCK_SIZE - bytes_have;
|
||||
unsigned int bytes_left = CURL_SHA512_256_BLOCK_SIZE - bytes_have;
|
||||
if(length >= bytes_left) {
|
||||
/* Combine new data with data in the buffer and process the full
|
||||
block. */
|
||||
@@ -660,12 +666,12 @@ MHDx_sha512_256_update(void *context,
|
||||
}
|
||||
}
|
||||
|
||||
while(SHA512_256_BLOCK_SIZE <= length) {
|
||||
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);
|
||||
data += SHA512_256_BLOCK_SIZE;
|
||||
length -= SHA512_256_BLOCK_SIZE;
|
||||
data += CURL_SHA512_256_BLOCK_SIZE;
|
||||
length -= CURL_SHA512_256_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
if(0 != length) {
|
||||
@@ -694,7 +700,8 @@ MHDx_sha512_256_update(void *context,
|
||||
* Finalise SHA-512/256 calculation, return digest.
|
||||
*
|
||||
* @param context the calculation context
|
||||
* @param[out] digest set to the hash, must be #SHA512_256_DIGEST_SIZE bytes
|
||||
* @param[out] digest set to the hash, must be #CURL_SHA512_256_DIGEST_SIZE
|
||||
# bytes
|
||||
* @return always CURLE_OK
|
||||
*/
|
||||
static CURLcode
|
||||
@@ -712,9 +719,9 @@ MHDx_sha512_256_finish(unsigned char *digest,
|
||||
not change the amount of hashed data. */
|
||||
num_bits = ctx->count << 3;
|
||||
|
||||
/* Note: (count & (SHA512_256_BLOCK_SIZE-1))
|
||||
equals (count % SHA512_256_BLOCK_SIZE) for this block size. */
|
||||
bytes_have = (unsigned int) (ctx->count & (SHA512_256_BLOCK_SIZE - 1));
|
||||
/* Note: (count & (CURL_SHA512_256_BLOCK_SIZE-1))
|
||||
equals (count % CURL_SHA512_256_BLOCK_SIZE) for this block size. */
|
||||
bytes_have = (unsigned int) (ctx->count & (CURL_SHA512_256_BLOCK_SIZE - 1));
|
||||
|
||||
/* Input data must be padded with a single bit "1", then with zeros and
|
||||
the finally the length of data in bits must be added as the final bytes
|
||||
@@ -728,12 +735,12 @@ MHDx_sha512_256_finish(unsigned char *digest,
|
||||
processed when formed). */
|
||||
((unsigned char *) ctx_buf)[bytes_have++] = 0x80U;
|
||||
|
||||
if(SHA512_256_BLOCK_SIZE - bytes_have < SHA512_256_SIZE_OF_LEN_ADD) {
|
||||
if(CURL_SHA512_256_BLOCK_SIZE - bytes_have < SHA512_256_SIZE_OF_LEN_ADD) {
|
||||
/* No space in the current block to put the total length of message.
|
||||
Pad the current block with zeros and process it. */
|
||||
if(bytes_have < SHA512_256_BLOCK_SIZE)
|
||||
if(bytes_have < CURL_SHA512_256_BLOCK_SIZE)
|
||||
memset(((unsigned char *) ctx_buf) + bytes_have, 0,
|
||||
SHA512_256_BLOCK_SIZE - bytes_have);
|
||||
CURL_SHA512_256_BLOCK_SIZE - bytes_have);
|
||||
/* Process the full block. */
|
||||
MHDx_sha512_256_transform(ctx->H, ctx->buffer);
|
||||
/* Start the new block. */
|
||||
@@ -742,17 +749,17 @@ MHDx_sha512_256_finish(unsigned char *digest,
|
||||
|
||||
/* Pad the rest of the buffer with zeros. */
|
||||
memset(((unsigned char *) ctx_buf) + bytes_have, 0,
|
||||
SHA512_256_BLOCK_SIZE - SHA512_256_SIZE_OF_LEN_ADD - bytes_have);
|
||||
CURL_SHA512_256_BLOCK_SIZE - SHA512_256_SIZE_OF_LEN_ADD - bytes_have);
|
||||
/* Put high part of number of bits in processed message and then lower
|
||||
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) \
|
||||
+ SHA512_256_BLOCK_SIZE \
|
||||
+ CURL_SHA512_256_BLOCK_SIZE \
|
||||
- SHA512_256_SIZE_OF_LEN_ADD, \
|
||||
ctx->count_bits_hi);
|
||||
MHDX_PUT_64BIT_BE(((unsigned char *) ctx_buf) \
|
||||
+ SHA512_256_BLOCK_SIZE \
|
||||
+ CURL_SHA512_256_BLOCK_SIZE \
|
||||
- SHA512_256_SIZE_OF_LEN_ADD \
|
||||
+ SHA512_256_BYTES_IN_WORD, \
|
||||
num_bits);
|
||||
@@ -841,9 +848,9 @@ const struct HMAC_params Curl_HMAC_SHA512_256[] = {
|
||||
/* Context structure size. */
|
||||
sizeof(Curl_sha512_256_ctx),
|
||||
/* Maximum key length (bytes). */
|
||||
SHA512_256_BLOCK_SIZE,
|
||||
CURL_SHA512_256_BLOCK_SIZE,
|
||||
/* Result length (bytes). */
|
||||
SHA512_256_DIGEST_SIZE
|
||||
CURL_SHA512_256_DIGEST_SIZE
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
extern const struct HMAC_params Curl_HMAC_SHA512_256[1];
|
||||
|
||||
#define SHA512_256_DIGEST_LENGTH 32
|
||||
#define CURL_SHA512_256_DIGEST_LENGTH 32
|
||||
|
||||
CURLcode
|
||||
Curl_sha512_256it(unsigned char *output, const unsigned char *input,
|
||||
|
||||
+13
-13
@@ -52,10 +52,10 @@ typedef PSecurityFunctionTable (APIENTRY *INITSECURITYINTERFACE_FN)(VOID);
|
||||
#endif
|
||||
|
||||
/* Handle of security.dll or secur32.dll, depending on Windows version */
|
||||
HMODULE s_hSecDll = NULL;
|
||||
HMODULE Curl_hSecDll = NULL;
|
||||
|
||||
/* Pointer to SSPI dispatch table */
|
||||
PSecurityFunctionTable s_pSecFn = NULL;
|
||||
PSecurityFunctionTable Curl_pSecFn = NULL;
|
||||
|
||||
/*
|
||||
* Curl_sspi_global_init()
|
||||
@@ -79,29 +79,29 @@ CURLcode Curl_sspi_global_init(void)
|
||||
INITSECURITYINTERFACE_FN pInitSecurityInterface;
|
||||
|
||||
/* If security interface is not yet initialized try to do this */
|
||||
if(!s_hSecDll) {
|
||||
if(!Curl_hSecDll) {
|
||||
/* Security Service Provider Interface (SSPI) functions are located in
|
||||
* security.dll on WinNT 4.0 and in secur32.dll on Win9x. Win2K and XP
|
||||
* have both these DLLs (security.dll forwards calls to secur32.dll) */
|
||||
|
||||
/* Load SSPI dll into the address space of the calling process */
|
||||
if(curlx_verify_windows_version(4, 0, 0, PLATFORM_WINNT, VERSION_EQUAL))
|
||||
s_hSecDll = Curl_load_library(TEXT("security.dll"));
|
||||
Curl_hSecDll = Curl_load_library(TEXT("security.dll"));
|
||||
else
|
||||
s_hSecDll = Curl_load_library(TEXT("secur32.dll"));
|
||||
if(!s_hSecDll)
|
||||
Curl_hSecDll = Curl_load_library(TEXT("secur32.dll"));
|
||||
if(!Curl_hSecDll)
|
||||
return CURLE_FAILED_INIT;
|
||||
|
||||
/* Get address of the InitSecurityInterfaceA function from the SSPI dll */
|
||||
pInitSecurityInterface =
|
||||
CURLX_FUNCTION_CAST(INITSECURITYINTERFACE_FN,
|
||||
(GetProcAddress(s_hSecDll, SECURITYENTRYPOINT)));
|
||||
(GetProcAddress(Curl_hSecDll, SECURITYENTRYPOINT)));
|
||||
if(!pInitSecurityInterface)
|
||||
return CURLE_FAILED_INIT;
|
||||
|
||||
/* Get pointer to Security Service Provider Interface dispatch table */
|
||||
s_pSecFn = pInitSecurityInterface();
|
||||
if(!s_pSecFn)
|
||||
Curl_pSecFn = pInitSecurityInterface();
|
||||
if(!Curl_pSecFn)
|
||||
return CURLE_FAILED_INIT;
|
||||
}
|
||||
|
||||
@@ -119,10 +119,10 @@ CURLcode Curl_sspi_global_init(void)
|
||||
*/
|
||||
void Curl_sspi_global_cleanup(void)
|
||||
{
|
||||
if(s_hSecDll) {
|
||||
FreeLibrary(s_hSecDll);
|
||||
s_hSecDll = NULL;
|
||||
s_pSecFn = NULL;
|
||||
if(Curl_hSecDll) {
|
||||
FreeLibrary(Curl_hSecDll);
|
||||
Curl_hSecDll = NULL;
|
||||
Curl_pSecFn = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -57,8 +57,8 @@ CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp,
|
||||
void Curl_sspi_free_identity(SEC_WINNT_AUTH_IDENTITY *identity);
|
||||
|
||||
/* Forward-declaration of global variables defined in curl_sspi.c */
|
||||
extern HMODULE s_hSecDll;
|
||||
extern PSecurityFunctionTable s_pSecFn;
|
||||
extern HMODULE Curl_hSecDll;
|
||||
extern PSecurityFunctionTable Curl_pSecFn;
|
||||
|
||||
/* Provide some definitions missing in old headers */
|
||||
#define SP_NAME_DIGEST "WDigest"
|
||||
|
||||
@@ -35,7 +35,9 @@
|
||||
#endif
|
||||
|
||||
#include "curl_threads.h"
|
||||
#ifdef BUILDING_LIBCURL
|
||||
#include "curl_memory.h"
|
||||
#endif
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
|
||||
+157
-58
@@ -53,6 +53,9 @@
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
#ifndef ARRAYSIZE
|
||||
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
|
||||
#endif
|
||||
|
||||
void Curl_debug(struct Curl_easy *data, curl_infotype type,
|
||||
char *ptr, size_t size)
|
||||
@@ -118,10 +121,16 @@ static void trc_infof(struct Curl_easy *data, struct curl_trc_feat *feat,
|
||||
const char * const fmt, va_list ap)
|
||||
{
|
||||
int len = 0;
|
||||
char buffer[MAXINFO + 2];
|
||||
char buffer[MAXINFO + 5];
|
||||
if(feat)
|
||||
len = msnprintf(buffer, MAXINFO, "[%s] ", feat->name);
|
||||
len += mvsnprintf(buffer + len, MAXINFO - len, fmt, ap);
|
||||
len = msnprintf(buffer, (MAXINFO + 1), "[%s] ", feat->name);
|
||||
len += mvsnprintf(buffer + len, (MAXINFO + 1) - len, fmt, ap);
|
||||
if(len >= MAXINFO) { /* too long, shorten with '...' */
|
||||
--len;
|
||||
buffer[len++] = '.';
|
||||
buffer[len++] = '.';
|
||||
buffer[len++] = '.';
|
||||
}
|
||||
buffer[len++] = '\n';
|
||||
buffer[len] = '\0';
|
||||
Curl_debug(data, CURLINFO_TEXT, buffer, len);
|
||||
@@ -212,58 +221,144 @@ void Curl_trc_ftp(struct Curl_easy *data, const char *fmt, ...)
|
||||
}
|
||||
#endif /* !CURL_DISABLE_FTP */
|
||||
|
||||
static struct curl_trc_feat *trc_feats[] = {
|
||||
&Curl_trc_feat_read,
|
||||
&Curl_trc_feat_write,
|
||||
#ifndef CURL_DISABLE_FTP
|
||||
&Curl_trc_feat_ftp,
|
||||
#endif
|
||||
#ifndef CURL_DISABLE_DOH
|
||||
&Curl_doh_trc,
|
||||
#endif
|
||||
NULL,
|
||||
#ifndef CURL_DISABLE_SMTP
|
||||
struct curl_trc_feat Curl_trc_feat_smtp = {
|
||||
"SMTP",
|
||||
CURL_LOG_LVL_NONE,
|
||||
};
|
||||
|
||||
static struct Curl_cftype *cf_types[] = {
|
||||
&Curl_cft_tcp,
|
||||
&Curl_cft_udp,
|
||||
&Curl_cft_unix,
|
||||
&Curl_cft_tcp_accept,
|
||||
&Curl_cft_happy_eyeballs,
|
||||
&Curl_cft_setup,
|
||||
void Curl_trc_smtp(struct Curl_easy *data, const char *fmt, ...)
|
||||
{
|
||||
DEBUGASSERT(!strchr(fmt, '\n'));
|
||||
if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_smtp)) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
trc_infof(data, &Curl_trc_feat_smtp, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#endif /* !CURL_DISABLE_SMTP */
|
||||
|
||||
#if defined(USE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
|
||||
struct curl_trc_feat Curl_trc_feat_ws = {
|
||||
"WS",
|
||||
CURL_LOG_LVL_NONE,
|
||||
};
|
||||
|
||||
void Curl_trc_ws(struct Curl_easy *data, const char *fmt, ...)
|
||||
{
|
||||
DEBUGASSERT(!strchr(fmt, '\n'));
|
||||
if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_ws)) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
trc_infof(data, &Curl_trc_feat_ws, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#endif /* USE_WEBSOCKETS && !CURL_DISABLE_HTTP */
|
||||
|
||||
#define TRC_CT_NONE (0)
|
||||
#define TRC_CT_PROTOCOL (1<<(0))
|
||||
#define TRC_CT_NETWORK (1<<(1))
|
||||
#define TRC_CT_PROXY (1<<(2))
|
||||
|
||||
struct trc_feat_def {
|
||||
struct curl_trc_feat *feat;
|
||||
unsigned int category;
|
||||
};
|
||||
|
||||
static struct trc_feat_def trc_feats[] = {
|
||||
{ &Curl_trc_feat_read, TRC_CT_NONE },
|
||||
{ &Curl_trc_feat_write, TRC_CT_NONE },
|
||||
#ifndef CURL_DISABLE_FTP
|
||||
{ &Curl_trc_feat_ftp, TRC_CT_PROTOCOL },
|
||||
#endif
|
||||
#ifndef CURL_DISABLE_DOH
|
||||
{ &Curl_doh_trc, TRC_CT_NETWORK },
|
||||
#endif
|
||||
#ifndef CURL_DISABLE_SMTP
|
||||
{ &Curl_trc_feat_smtp, TRC_CT_PROTOCOL },
|
||||
#endif
|
||||
#if defined(USE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
|
||||
{ &Curl_trc_feat_ws, TRC_CT_PROTOCOL },
|
||||
#endif
|
||||
};
|
||||
|
||||
struct trc_cft_def {
|
||||
struct Curl_cftype *cft;
|
||||
unsigned int category;
|
||||
};
|
||||
|
||||
static struct trc_cft_def trc_cfts[] = {
|
||||
{ &Curl_cft_tcp, TRC_CT_NETWORK },
|
||||
{ &Curl_cft_udp, TRC_CT_NETWORK },
|
||||
{ &Curl_cft_unix, TRC_CT_NETWORK },
|
||||
{ &Curl_cft_tcp_accept, TRC_CT_NETWORK },
|
||||
{ &Curl_cft_happy_eyeballs, TRC_CT_NETWORK },
|
||||
{ &Curl_cft_setup, TRC_CT_PROTOCOL },
|
||||
#ifdef USE_NGHTTP2
|
||||
&Curl_cft_nghttp2,
|
||||
{ &Curl_cft_nghttp2, TRC_CT_PROTOCOL },
|
||||
#endif
|
||||
#ifdef USE_SSL
|
||||
&Curl_cft_ssl,
|
||||
{ &Curl_cft_ssl, TRC_CT_NETWORK },
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
&Curl_cft_ssl_proxy,
|
||||
{ &Curl_cft_ssl_proxy, TRC_CT_PROXY },
|
||||
#endif
|
||||
#endif
|
||||
#if !defined(CURL_DISABLE_PROXY)
|
||||
#if !defined(CURL_DISABLE_HTTP)
|
||||
&Curl_cft_h1_proxy,
|
||||
{ &Curl_cft_h1_proxy, TRC_CT_PROXY },
|
||||
#ifdef USE_NGHTTP2
|
||||
&Curl_cft_h2_proxy,
|
||||
{ &Curl_cft_h2_proxy, TRC_CT_PROXY },
|
||||
#endif
|
||||
&Curl_cft_http_proxy,
|
||||
{ &Curl_cft_http_proxy, TRC_CT_PROXY },
|
||||
#endif /* !CURL_DISABLE_HTTP */
|
||||
&Curl_cft_haproxy,
|
||||
&Curl_cft_socks_proxy,
|
||||
{ &Curl_cft_haproxy, TRC_CT_PROXY },
|
||||
{ &Curl_cft_socks_proxy, TRC_CT_PROXY },
|
||||
#endif /* !CURL_DISABLE_PROXY */
|
||||
#ifdef USE_HTTP3
|
||||
&Curl_cft_http3,
|
||||
{ &Curl_cft_http3, TRC_CT_PROTOCOL },
|
||||
#endif
|
||||
#if !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER)
|
||||
&Curl_cft_http_connect,
|
||||
{ &Curl_cft_http_connect, TRC_CT_PROTOCOL },
|
||||
#endif
|
||||
NULL,
|
||||
};
|
||||
|
||||
CURLcode Curl_trc_opt(const char *config)
|
||||
static void trc_apply_level_by_name(const char * const token, int lvl)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for(i = 0; i < ARRAYSIZE(trc_cfts); ++i) {
|
||||
if(strcasecompare(token, trc_cfts[i].cft->name)) {
|
||||
trc_cfts[i].cft->log_level = lvl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(i = 0; i < ARRAYSIZE(trc_feats); ++i) {
|
||||
if(strcasecompare(token, trc_feats[i].feat->name)) {
|
||||
trc_feats[i].feat->log_level = lvl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void trc_apply_level_by_category(int category, int lvl)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for(i = 0; i < ARRAYSIZE(trc_cfts); ++i) {
|
||||
if(!category || (trc_cfts[i].category & category))
|
||||
trc_cfts[i].cft->log_level = lvl;
|
||||
}
|
||||
for(i = 0; i < ARRAYSIZE(trc_feats); ++i) {
|
||||
if(!category || (trc_feats[i].category & category))
|
||||
trc_feats[i].feat->log_level = lvl;
|
||||
}
|
||||
}
|
||||
|
||||
static CURLcode trc_opt(const char *config)
|
||||
{
|
||||
char *token, *tok_buf, *tmp;
|
||||
size_t i;
|
||||
int lvl;
|
||||
|
||||
tmp = strdup(config);
|
||||
@@ -285,42 +380,46 @@ CURLcode Curl_trc_opt(const char *config)
|
||||
lvl = CURL_LOG_LVL_INFO;
|
||||
break;
|
||||
}
|
||||
for(i = 0; cf_types[i]; ++i) {
|
||||
if(strcasecompare(token, "all")) {
|
||||
cf_types[i]->log_level = lvl;
|
||||
}
|
||||
else if(strcasecompare(token, cf_types[i]->name)) {
|
||||
cf_types[i]->log_level = lvl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(i = 0; trc_feats[i]; ++i) {
|
||||
if(strcasecompare(token, "all")) {
|
||||
trc_feats[i]->log_level = lvl;
|
||||
}
|
||||
else if(strcasecompare(token, trc_feats[i]->name)) {
|
||||
trc_feats[i]->log_level = lvl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(strcasecompare(token, "all"))
|
||||
trc_apply_level_by_category(TRC_CT_NONE, lvl);
|
||||
else if(strcasecompare(token, "protocol"))
|
||||
trc_apply_level_by_category(TRC_CT_PROTOCOL, lvl);
|
||||
else if(strcasecompare(token, "network"))
|
||||
trc_apply_level_by_category(TRC_CT_NETWORK, lvl);
|
||||
else if(strcasecompare(token, "proxy"))
|
||||
trc_apply_level_by_category(TRC_CT_PROXY, lvl);
|
||||
else
|
||||
trc_apply_level_by_name(token, lvl);
|
||||
|
||||
token = strtok_r(NULL, ", ", &tok_buf);
|
||||
}
|
||||
free(tmp);
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
CURLcode Curl_trc_opt(const char *config)
|
||||
{
|
||||
CURLcode result = config? trc_opt(config) : CURLE_OK;
|
||||
#ifdef DEBUGBUILD
|
||||
/* CURL_DEBUG can override anything */
|
||||
if(!result) {
|
||||
const char *dbg_config = getenv("CURL_DEBUG");
|
||||
if(dbg_config)
|
||||
result = trc_opt(dbg_config);
|
||||
}
|
||||
#endif /* DEBUGBUILD */
|
||||
return result;
|
||||
}
|
||||
|
||||
CURLcode Curl_trc_init(void)
|
||||
{
|
||||
#ifdef DEBUGBUILD
|
||||
/* WIP: we use the auto-init from an env var only in DEBUG builds for
|
||||
* convenience. */
|
||||
const char *config = getenv("CURL_DEBUG");
|
||||
if(config) {
|
||||
return Curl_trc_opt(config);
|
||||
}
|
||||
#endif /* DEBUGBUILD */
|
||||
return Curl_trc_opt(NULL);
|
||||
#else
|
||||
return CURLE_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
#else /* defined(CURL_DISABLE_VERBOSE_STRINGS) */
|
||||
|
||||
CURLcode Curl_trc_init(void)
|
||||
|
||||
@@ -89,6 +89,16 @@ void Curl_failf(struct Curl_easy *data,
|
||||
do { if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_ftp)) \
|
||||
Curl_trc_ftp(data, __VA_ARGS__); } while(0)
|
||||
#endif /* !CURL_DISABLE_FTP */
|
||||
#ifndef CURL_DISABLE_SMTP
|
||||
#define CURL_TRC_SMTP(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 */
|
||||
#if defined(USE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
|
||||
#define CURL_TRC_WS(data, ...) \
|
||||
do { if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_ws)) \
|
||||
Curl_trc_ws(data, __VA_ARGS__); } while(0)
|
||||
#endif /* USE_WEBSOCKETS && !CURL_DISABLE_HTTP */
|
||||
|
||||
#else /* CURL_HAVE_C99 */
|
||||
|
||||
@@ -100,6 +110,12 @@ void Curl_failf(struct Curl_easy *data,
|
||||
#ifndef CURL_DISABLE_FTP
|
||||
#define CURL_TRC_FTP Curl_trc_ftp
|
||||
#endif
|
||||
#ifndef CURL_DISABLE_SMTP
|
||||
#define CURL_TRC_SMTP Curl_trc_smtp
|
||||
#endif
|
||||
#if defined(USE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
|
||||
#define CURL_TRC_WS Curl_trc_ws
|
||||
#endif
|
||||
|
||||
#endif /* !CURL_HAVE_C99 */
|
||||
|
||||
@@ -148,6 +164,16 @@ 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(USE_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) */
|
||||
@@ -194,6 +220,12 @@ 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
|
||||
|
||||
#endif /* !defined(CURL_DISABLE_VERBOSE_STRINGS) */
|
||||
|
||||
|
||||
+2
-41
@@ -31,10 +31,8 @@
|
||||
* be.
|
||||
*/
|
||||
|
||||
#include <curl/mprintf.h>
|
||||
/* this is still a public header file that provides the curl_mprintf()
|
||||
functions while they still are offered publicly. They will be made library-
|
||||
private one day */
|
||||
/* map standard printf functions to curl implementations */
|
||||
#include "curl_printf.h"
|
||||
|
||||
#include "strcase.h"
|
||||
/* "strcase.h" provides the strcasecompare protos */
|
||||
@@ -77,41 +75,4 @@
|
||||
|
||||
*/
|
||||
|
||||
#define curlx_mvsnprintf curl_mvsnprintf
|
||||
#define curlx_msnprintf curl_msnprintf
|
||||
#define curlx_maprintf curl_maprintf
|
||||
#define curlx_mvaprintf curl_mvaprintf
|
||||
#define curlx_msprintf curl_msprintf
|
||||
#define curlx_mprintf curl_mprintf
|
||||
#define curlx_mfprintf curl_mfprintf
|
||||
#define curlx_mvsprintf curl_mvsprintf
|
||||
#define curlx_mvprintf curl_mvprintf
|
||||
#define curlx_mvfprintf curl_mvfprintf
|
||||
|
||||
#ifdef ENABLE_CURLX_PRINTF
|
||||
/* If this define is set, we define all "standard" printf() functions to use
|
||||
the curlx_* version instead. It makes the source code transparent and
|
||||
easier to understand/patch. Undefine them first. */
|
||||
# undef printf
|
||||
# undef fprintf
|
||||
# undef sprintf
|
||||
# undef msnprintf
|
||||
# undef vprintf
|
||||
# undef vfprintf
|
||||
# undef vsprintf
|
||||
# undef mvsnprintf
|
||||
# undef aprintf
|
||||
# undef vaprintf
|
||||
|
||||
# define printf curlx_mprintf
|
||||
# define fprintf curlx_mfprintf
|
||||
# define sprintf curlx_msprintf
|
||||
# define msnprintf curlx_msnprintf
|
||||
# define vprintf curlx_mvprintf
|
||||
# define vfprintf curlx_mvfprintf
|
||||
# define mvsnprintf curlx_mvsnprintf
|
||||
# define aprintf curlx_maprintf
|
||||
# define vaprintf curlx_mvaprintf
|
||||
#endif /* ENABLE_CURLX_PRINTF */
|
||||
|
||||
#endif /* HEADER_CURL_CURLX_H */
|
||||
|
||||
+1
-1
@@ -146,7 +146,7 @@ static CURLcode sendf(struct Curl_easy *data, const char *fmt, ...)
|
||||
|
||||
for(;;) {
|
||||
/* Write the buffer to the socket */
|
||||
result = Curl_xfer_send(data, sptr, write_len, &bytes_written);
|
||||
result = Curl_xfer_send(data, sptr, write_len, FALSE, &bytes_written);
|
||||
|
||||
if(result)
|
||||
break;
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
|
||||
#define DNS_CLASS_IN 0x01
|
||||
|
||||
/* local_print_buf truncates if the hex string will be more than this */
|
||||
/* doh_print_buf truncates if the hex string will be more than this */
|
||||
#define LOCAL_PB_HEXMAX 400
|
||||
|
||||
#ifndef CURL_DISABLE_VERBOSE_STRINGS
|
||||
@@ -82,11 +82,11 @@ struct curl_trc_feat Curl_doh_trc = {
|
||||
|
||||
/* @unittest 1655
|
||||
*/
|
||||
UNITTEST DOHcode doh_encode(const char *host,
|
||||
DNStype dnstype,
|
||||
unsigned char *dnsp, /* buffer */
|
||||
size_t len, /* buffer size */
|
||||
size_t *olen) /* output length */
|
||||
UNITTEST DOHcode doh_req_encode(const char *host,
|
||||
DNStype dnstype,
|
||||
unsigned char *dnsp, /* buffer */
|
||||
size_t len, /* buffer size */
|
||||
size_t *olen) /* output length */
|
||||
{
|
||||
const size_t hostlen = strlen(host);
|
||||
unsigned char *orig = dnsp;
|
||||
@@ -192,9 +192,9 @@ doh_write_cb(const void *contents, size_t size, size_t nmemb, void *userp)
|
||||
}
|
||||
|
||||
#if defined(USE_HTTPSRR) && defined(DEBUGBUILD)
|
||||
static void local_print_buf(struct Curl_easy *data,
|
||||
const char *prefix,
|
||||
unsigned char *buf, size_t len)
|
||||
static void doh_print_buf(struct Curl_easy *data,
|
||||
const char *prefix,
|
||||
unsigned char *buf, size_t len)
|
||||
{
|
||||
unsigned char hexstr[LOCAL_PB_HEXMAX];
|
||||
size_t hlen = LOCAL_PB_HEXMAX;
|
||||
@@ -214,19 +214,26 @@ static void local_print_buf(struct Curl_easy *data,
|
||||
/* called from multi.c when this DoH transfer is complete */
|
||||
static int doh_done(struct Curl_easy *doh, CURLcode result)
|
||||
{
|
||||
struct Curl_easy *data = doh->set.dohfor;
|
||||
struct dohdata *dohp = data->req.doh;
|
||||
/* so one of the DoH request done for the 'data' transfer is now complete! */
|
||||
dohp->pending--;
|
||||
infof(doh, "a DoH request is completed, %u to go", dohp->pending);
|
||||
if(result)
|
||||
infof(doh, "DoH request %s", curl_easy_strerror(result));
|
||||
struct Curl_easy *data; /* the transfer that asked for the DoH probe */
|
||||
|
||||
if(!dohp->pending) {
|
||||
/* DoH completed */
|
||||
curl_slist_free_all(dohp->headers);
|
||||
dohp->headers = NULL;
|
||||
Curl_expire(data, 0, EXPIRE_RUN_NOW);
|
||||
data = Curl_multi_get_handle(doh->multi, doh->set.dohfor_mid);
|
||||
if(!data) {
|
||||
DEBUGF(infof(doh, "doh_done: xfer for mid=%" FMT_OFF_T
|
||||
" not found", doh->set.dohfor_mid));
|
||||
DEBUGASSERT(0);
|
||||
}
|
||||
else {
|
||||
struct doh_probes *dohp = data->req.doh;
|
||||
/* one of the DoH request done for the 'data' transfer is now complete! */
|
||||
dohp->pending--;
|
||||
infof(doh, "a DoH request is completed, %u to go", dohp->pending);
|
||||
if(result)
|
||||
infof(doh, "DoH request %s", curl_easy_strerror(result));
|
||||
|
||||
if(!dohp->pending) {
|
||||
/* DoH completed, run the transfer picking up the results */
|
||||
Curl_expire(data, 0, EXPIRE_RUN_NOW);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -240,24 +247,24 @@ do { \
|
||||
goto error; \
|
||||
} while(0)
|
||||
|
||||
static CURLcode dohprobe(struct Curl_easy *data,
|
||||
struct dnsprobe *p, DNStype dnstype,
|
||||
const char *host,
|
||||
const char *url, CURLM *multi,
|
||||
struct curl_slist *headers)
|
||||
static CURLcode doh_run_probe(struct Curl_easy *data,
|
||||
struct doh_probe *p, DNStype dnstype,
|
||||
const char *host,
|
||||
const char *url, CURLM *multi,
|
||||
struct curl_slist *headers)
|
||||
{
|
||||
struct Curl_easy *doh = NULL;
|
||||
CURLcode result = CURLE_OK;
|
||||
timediff_t timeout_ms;
|
||||
DOHcode d = doh_encode(host, dnstype, p->dohbuffer, sizeof(p->dohbuffer),
|
||||
&p->dohlen);
|
||||
DOHcode d = doh_req_encode(host, dnstype, p->req_body, sizeof(p->req_body),
|
||||
&p->req_body_len);
|
||||
if(d) {
|
||||
failf(data, "Failed to encode DoH packet [%d]", d);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
p->dnstype = dnstype;
|
||||
Curl_dyn_init(&p->serverdoh, DYN_DOH_RESPONSE);
|
||||
Curl_dyn_init(&p->resp_body, DYN_DOH_RESPONSE);
|
||||
|
||||
timeout_ms = Curl_timeleft(data, NULL, TRUE);
|
||||
if(timeout_ms <= 0) {
|
||||
@@ -266,126 +273,126 @@ static CURLcode dohprobe(struct Curl_easy *data,
|
||||
}
|
||||
/* Curl_open() is the internal version of curl_easy_init() */
|
||||
result = Curl_open(&doh);
|
||||
if(!result) {
|
||||
/* pass in the struct pointer via a local variable to please coverity and
|
||||
the gcc typecheck helpers */
|
||||
struct dynbuf *resp = &p->serverdoh;
|
||||
doh->state.internal = true;
|
||||
if(result)
|
||||
goto error;
|
||||
|
||||
/* pass in the struct pointer via a local variable to please coverity and
|
||||
the gcc typecheck helpers */
|
||||
doh->state.internal = true;
|
||||
#ifndef CURL_DISABLE_VERBOSE_STRINGS
|
||||
doh->state.feat = &Curl_doh_trc;
|
||||
doh->state.feat = &Curl_doh_trc;
|
||||
#endif
|
||||
ERROR_CHECK_SETOPT(CURLOPT_URL, url);
|
||||
ERROR_CHECK_SETOPT(CURLOPT_DEFAULT_PROTOCOL, "https");
|
||||
ERROR_CHECK_SETOPT(CURLOPT_WRITEFUNCTION, doh_write_cb);
|
||||
ERROR_CHECK_SETOPT(CURLOPT_WRITEDATA, resp);
|
||||
ERROR_CHECK_SETOPT(CURLOPT_POSTFIELDS, p->dohbuffer);
|
||||
ERROR_CHECK_SETOPT(CURLOPT_POSTFIELDSIZE, (long)p->dohlen);
|
||||
ERROR_CHECK_SETOPT(CURLOPT_HTTPHEADER, headers);
|
||||
ERROR_CHECK_SETOPT(CURLOPT_URL, url);
|
||||
ERROR_CHECK_SETOPT(CURLOPT_DEFAULT_PROTOCOL, "https");
|
||||
ERROR_CHECK_SETOPT(CURLOPT_WRITEFUNCTION, doh_write_cb);
|
||||
ERROR_CHECK_SETOPT(CURLOPT_WRITEDATA, &p->resp_body);
|
||||
ERROR_CHECK_SETOPT(CURLOPT_POSTFIELDS, p->req_body);
|
||||
ERROR_CHECK_SETOPT(CURLOPT_POSTFIELDSIZE, (long)p->req_body_len);
|
||||
ERROR_CHECK_SETOPT(CURLOPT_HTTPHEADER, headers);
|
||||
#ifdef USE_HTTP2
|
||||
ERROR_CHECK_SETOPT(CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS);
|
||||
ERROR_CHECK_SETOPT(CURLOPT_PIPEWAIT, 1L);
|
||||
ERROR_CHECK_SETOPT(CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS);
|
||||
ERROR_CHECK_SETOPT(CURLOPT_PIPEWAIT, 1L);
|
||||
#endif
|
||||
#ifndef DEBUGBUILD
|
||||
/* enforce HTTPS if not debug */
|
||||
ERROR_CHECK_SETOPT(CURLOPT_PROTOCOLS, CURLPROTO_HTTPS);
|
||||
/* enforce HTTPS if not debug */
|
||||
ERROR_CHECK_SETOPT(CURLOPT_PROTOCOLS, CURLPROTO_HTTPS);
|
||||
#else
|
||||
/* in debug mode, also allow http */
|
||||
ERROR_CHECK_SETOPT(CURLOPT_PROTOCOLS, CURLPROTO_HTTP|CURLPROTO_HTTPS);
|
||||
/* in debug mode, also allow http */
|
||||
ERROR_CHECK_SETOPT(CURLOPT_PROTOCOLS, CURLPROTO_HTTP|CURLPROTO_HTTPS);
|
||||
#endif
|
||||
ERROR_CHECK_SETOPT(CURLOPT_TIMEOUT_MS, (long)timeout_ms);
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SHARE, data->share);
|
||||
if(data->set.err && data->set.err != stderr)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_STDERR, data->set.err);
|
||||
if(Curl_trc_ft_is_verbose(data, &Curl_doh_trc))
|
||||
ERROR_CHECK_SETOPT(CURLOPT_VERBOSE, 1L);
|
||||
if(data->set.no_signal)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_NOSIGNAL, 1L);
|
||||
ERROR_CHECK_SETOPT(CURLOPT_TIMEOUT_MS, (long)timeout_ms);
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SHARE, data->share);
|
||||
if(data->set.err && data->set.err != stderr)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_STDERR, data->set.err);
|
||||
if(Curl_trc_ft_is_verbose(data, &Curl_doh_trc))
|
||||
ERROR_CHECK_SETOPT(CURLOPT_VERBOSE, 1L);
|
||||
if(data->set.no_signal)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_NOSIGNAL, 1L);
|
||||
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYHOST,
|
||||
data->set.doh_verifyhost ? 2L : 0L);
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYPEER,
|
||||
data->set.doh_verifypeer ? 1L : 0L);
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYSTATUS,
|
||||
data->set.doh_verifystatus ? 1L : 0L);
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYHOST,
|
||||
data->set.doh_verifyhost ? 2L : 0L);
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYPEER,
|
||||
data->set.doh_verifypeer ? 1L : 0L);
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYSTATUS,
|
||||
data->set.doh_verifystatus ? 1L : 0L);
|
||||
|
||||
/* Inherit *some* SSL options from the user's transfer. This is a
|
||||
best-guess as to which options are needed for compatibility. #3661
|
||||
/* Inherit *some* SSL options from the user's transfer. This is a
|
||||
best-guess as to which options are needed for compatibility. #3661
|
||||
|
||||
Note DoH does not inherit the user's proxy server so proxy SSL settings
|
||||
have no effect and are not inherited. If that changes then two new
|
||||
options should be added to check doh proxy insecure separately,
|
||||
CURLOPT_DOH_PROXY_SSL_VERIFYHOST and CURLOPT_DOH_PROXY_SSL_VERIFYPEER.
|
||||
*/
|
||||
if(data->set.ssl.falsestart)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SSL_FALSESTART, 1L);
|
||||
if(data->set.str[STRING_SSL_CAFILE]) {
|
||||
ERROR_CHECK_SETOPT(CURLOPT_CAINFO,
|
||||
data->set.str[STRING_SSL_CAFILE]);
|
||||
}
|
||||
if(data->set.blobs[BLOB_CAINFO]) {
|
||||
ERROR_CHECK_SETOPT(CURLOPT_CAINFO_BLOB,
|
||||
data->set.blobs[BLOB_CAINFO]);
|
||||
}
|
||||
if(data->set.str[STRING_SSL_CAPATH]) {
|
||||
ERROR_CHECK_SETOPT(CURLOPT_CAPATH,
|
||||
data->set.str[STRING_SSL_CAPATH]);
|
||||
}
|
||||
if(data->set.str[STRING_SSL_CRLFILE]) {
|
||||
ERROR_CHECK_SETOPT(CURLOPT_CRLFILE,
|
||||
data->set.str[STRING_SSL_CRLFILE]);
|
||||
}
|
||||
if(data->set.ssl.certinfo)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_CERTINFO, 1L);
|
||||
if(data->set.ssl.fsslctx)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_FUNCTION, data->set.ssl.fsslctx);
|
||||
if(data->set.ssl.fsslctxp)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_DATA, data->set.ssl.fsslctxp);
|
||||
if(data->set.fdebug)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_DEBUGFUNCTION, data->set.fdebug);
|
||||
if(data->set.debugdata)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_DEBUGDATA, data->set.debugdata);
|
||||
if(data->set.str[STRING_SSL_EC_CURVES]) {
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SSL_EC_CURVES,
|
||||
data->set.str[STRING_SSL_EC_CURVES]);
|
||||
}
|
||||
|
||||
{
|
||||
long mask =
|
||||
(data->set.ssl.enable_beast ?
|
||||
CURLSSLOPT_ALLOW_BEAST : 0) |
|
||||
(data->set.ssl.no_revoke ?
|
||||
CURLSSLOPT_NO_REVOKE : 0) |
|
||||
(data->set.ssl.no_partialchain ?
|
||||
CURLSSLOPT_NO_PARTIALCHAIN : 0) |
|
||||
(data->set.ssl.revoke_best_effort ?
|
||||
CURLSSLOPT_REVOKE_BEST_EFFORT : 0) |
|
||||
(data->set.ssl.native_ca_store ?
|
||||
CURLSSLOPT_NATIVE_CA : 0) |
|
||||
(data->set.ssl.auto_client_cert ?
|
||||
CURLSSLOPT_AUTO_CLIENT_CERT : 0);
|
||||
|
||||
(void)curl_easy_setopt(doh, CURLOPT_SSL_OPTIONS, mask);
|
||||
}
|
||||
|
||||
doh->set.fmultidone = doh_done;
|
||||
doh->set.dohfor = data; /* identify for which transfer this is done */
|
||||
p->easy = doh;
|
||||
|
||||
/* DoH handles must not inherit private_data. The handles may be passed to
|
||||
the user via callbacks and the user will be able to identify them as
|
||||
internal handles because private data is not set. The user can then set
|
||||
private_data via CURLOPT_PRIVATE if they so choose. */
|
||||
DEBUGASSERT(!doh->set.private_data);
|
||||
|
||||
if(curl_multi_add_handle(multi, doh))
|
||||
goto error;
|
||||
Note DoH does not inherit the user's proxy server so proxy SSL settings
|
||||
have no effect and are not inherited. If that changes then two new
|
||||
options should be added to check doh proxy insecure separately,
|
||||
CURLOPT_DOH_PROXY_SSL_VERIFYHOST and CURLOPT_DOH_PROXY_SSL_VERIFYPEER.
|
||||
*/
|
||||
if(data->set.ssl.falsestart)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SSL_FALSESTART, 1L);
|
||||
if(data->set.str[STRING_SSL_CAFILE]) {
|
||||
ERROR_CHECK_SETOPT(CURLOPT_CAINFO,
|
||||
data->set.str[STRING_SSL_CAFILE]);
|
||||
}
|
||||
else
|
||||
if(data->set.blobs[BLOB_CAINFO]) {
|
||||
ERROR_CHECK_SETOPT(CURLOPT_CAINFO_BLOB,
|
||||
data->set.blobs[BLOB_CAINFO]);
|
||||
}
|
||||
if(data->set.str[STRING_SSL_CAPATH]) {
|
||||
ERROR_CHECK_SETOPT(CURLOPT_CAPATH,
|
||||
data->set.str[STRING_SSL_CAPATH]);
|
||||
}
|
||||
if(data->set.str[STRING_SSL_CRLFILE]) {
|
||||
ERROR_CHECK_SETOPT(CURLOPT_CRLFILE,
|
||||
data->set.str[STRING_SSL_CRLFILE]);
|
||||
}
|
||||
if(data->set.ssl.certinfo)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_CERTINFO, 1L);
|
||||
if(data->set.ssl.fsslctx)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_FUNCTION, data->set.ssl.fsslctx);
|
||||
if(data->set.ssl.fsslctxp)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_DATA, data->set.ssl.fsslctxp);
|
||||
if(data->set.fdebug)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_DEBUGFUNCTION, data->set.fdebug);
|
||||
if(data->set.debugdata)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_DEBUGDATA, data->set.debugdata);
|
||||
if(data->set.str[STRING_SSL_EC_CURVES]) {
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SSL_EC_CURVES,
|
||||
data->set.str[STRING_SSL_EC_CURVES]);
|
||||
}
|
||||
|
||||
{
|
||||
long mask =
|
||||
(data->set.ssl.enable_beast ?
|
||||
CURLSSLOPT_ALLOW_BEAST : 0) |
|
||||
(data->set.ssl.no_revoke ?
|
||||
CURLSSLOPT_NO_REVOKE : 0) |
|
||||
(data->set.ssl.no_partialchain ?
|
||||
CURLSSLOPT_NO_PARTIALCHAIN : 0) |
|
||||
(data->set.ssl.revoke_best_effort ?
|
||||
CURLSSLOPT_REVOKE_BEST_EFFORT : 0) |
|
||||
(data->set.ssl.native_ca_store ?
|
||||
CURLSSLOPT_NATIVE_CA : 0) |
|
||||
(data->set.ssl.auto_client_cert ?
|
||||
CURLSSLOPT_AUTO_CLIENT_CERT : 0);
|
||||
|
||||
(void)curl_easy_setopt(doh, CURLOPT_SSL_OPTIONS, mask);
|
||||
}
|
||||
|
||||
doh->set.fmultidone = doh_done;
|
||||
doh->set.dohfor_mid = data->mid; /* for which transfer this is done */
|
||||
|
||||
/* DoH handles must not inherit private_data. The handles may be passed to
|
||||
the user via callbacks and the user will be able to identify them as
|
||||
internal handles because private data is not set. The user can then set
|
||||
private_data via CURLOPT_PRIVATE if they so choose. */
|
||||
DEBUGASSERT(!doh->set.private_data);
|
||||
|
||||
if(curl_multi_add_handle(multi, doh))
|
||||
goto error;
|
||||
|
||||
p->easy_mid = doh->mid;
|
||||
return CURLE_OK;
|
||||
|
||||
error:
|
||||
Curl_close(&doh);
|
||||
p->easy_mid = -1;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -400,8 +407,9 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
|
||||
int *waitp)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct dohdata *dohp;
|
||||
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
|
||||
@@ -416,23 +424,27 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
|
||||
DEBUGASSERT(conn);
|
||||
|
||||
/* start clean, consider allocating this struct on demand */
|
||||
dohp = data->req.doh = calloc(1, sizeof(struct dohdata));
|
||||
dohp = data->req.doh = calloc(1, sizeof(struct doh_probes));
|
||||
if(!dohp)
|
||||
return NULL;
|
||||
|
||||
for(i = 0; i < DOH_SLOT_COUNT; ++i) {
|
||||
dohp->probe[i].easy_mid = -1;
|
||||
}
|
||||
|
||||
conn->bits.doh = TRUE;
|
||||
dohp->host = hostname;
|
||||
dohp->port = port;
|
||||
dohp->headers =
|
||||
dohp->req_hds =
|
||||
curl_slist_append(NULL,
|
||||
"Content-Type: application/dns-message");
|
||||
if(!dohp->headers)
|
||||
if(!dohp->req_hds)
|
||||
goto error;
|
||||
|
||||
/* create IPv4 DoH request */
|
||||
result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_IPADDR_V4],
|
||||
DNS_TYPE_A, hostname, data->set.str[STRING_DOH],
|
||||
data->multi, dohp->headers);
|
||||
result = doh_run_probe(data, &dohp->probe[DOH_SLOT_IPV4],
|
||||
DNS_TYPE_A, hostname, data->set.str[STRING_DOH],
|
||||
data->multi, dohp->req_hds);
|
||||
if(result)
|
||||
goto error;
|
||||
dohp->pending++;
|
||||
@@ -440,9 +452,9 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
|
||||
#ifdef USE_IPV6
|
||||
if((conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data)) {
|
||||
/* create IPv6 DoH request */
|
||||
result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_IPADDR_V6],
|
||||
DNS_TYPE_AAAA, hostname, data->set.str[STRING_DOH],
|
||||
data->multi, dohp->headers);
|
||||
result = doh_run_probe(data, &dohp->probe[DOH_SLOT_IPV6],
|
||||
DNS_TYPE_AAAA, hostname, data->set.str[STRING_DOH],
|
||||
data->multi, dohp->req_hds);
|
||||
if(result)
|
||||
goto error;
|
||||
dohp->pending++;
|
||||
@@ -469,9 +481,9 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
|
||||
qname = aprintf("_%d._https.%s", port, hostname);
|
||||
if(!qname)
|
||||
goto error;
|
||||
result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_HTTPS],
|
||||
DNS_TYPE_HTTPS, qname, data->set.str[STRING_DOH],
|
||||
data->multi, dohp->headers);
|
||||
result = doh_run_probe(data, &dohp->probe[DOH_SLOT_HTTPS_RR],
|
||||
DNS_TYPE_HTTPS, qname, data->set.str[STRING_DOH],
|
||||
data->multi, dohp->req_hds);
|
||||
Curl_safefree(qname);
|
||||
if(result)
|
||||
goto error;
|
||||
@@ -487,8 +499,8 @@ error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static DOHcode skipqname(const unsigned char *doh, size_t dohlen,
|
||||
unsigned int *indexp)
|
||||
static DOHcode doh_skipqname(const unsigned char *doh, size_t dohlen,
|
||||
unsigned int *indexp)
|
||||
{
|
||||
unsigned char length;
|
||||
do {
|
||||
@@ -511,12 +523,13 @@ static DOHcode skipqname(const unsigned char *doh, size_t dohlen,
|
||||
return DOH_OK;
|
||||
}
|
||||
|
||||
static unsigned short get16bit(const unsigned char *doh, unsigned int index)
|
||||
static unsigned short doh_get16bit(const unsigned char *doh,
|
||||
unsigned int index)
|
||||
{
|
||||
return (unsigned short)((doh[index] << 8) | doh[index + 1]);
|
||||
}
|
||||
|
||||
static unsigned int get32bit(const unsigned char *doh, unsigned int index)
|
||||
static unsigned int doh_get32bit(const unsigned char *doh, unsigned int index)
|
||||
{
|
||||
/* make clang and gcc optimize this to bswap by incrementing
|
||||
the pointer first. */
|
||||
@@ -529,7 +542,8 @@ static unsigned int get32bit(const unsigned char *doh, unsigned int index)
|
||||
((unsigned)doh[2] << 8) | doh[3];
|
||||
}
|
||||
|
||||
static DOHcode store_a(const unsigned char *doh, int index, struct dohentry *d)
|
||||
static void doh_store_a(const unsigned char *doh, int index,
|
||||
struct dohentry *d)
|
||||
{
|
||||
/* silently ignore addresses over the limit */
|
||||
if(d->numaddr < DOH_MAX_ADDR) {
|
||||
@@ -538,12 +552,10 @@ static DOHcode store_a(const unsigned char *doh, int index, struct dohentry *d)
|
||||
memcpy(&a->ip.v4, &doh[index], 4);
|
||||
d->numaddr++;
|
||||
}
|
||||
return DOH_OK;
|
||||
}
|
||||
|
||||
static DOHcode store_aaaa(const unsigned char *doh,
|
||||
int index,
|
||||
struct dohentry *d)
|
||||
static void doh_store_aaaa(const unsigned char *doh, int index,
|
||||
struct dohentry *d)
|
||||
{
|
||||
/* silently ignore addresses over the limit */
|
||||
if(d->numaddr < DOH_MAX_ADDR) {
|
||||
@@ -552,14 +564,11 @@ static DOHcode store_aaaa(const unsigned char *doh,
|
||||
memcpy(&a->ip.v6, &doh[index], 16);
|
||||
d->numaddr++;
|
||||
}
|
||||
return DOH_OK;
|
||||
}
|
||||
|
||||
#ifdef USE_HTTPSRR
|
||||
static DOHcode store_https(const unsigned char *doh,
|
||||
int index,
|
||||
struct dohentry *d,
|
||||
uint16_t len)
|
||||
static DOHcode doh_store_https(const unsigned char *doh, int index,
|
||||
struct dohentry *d, uint16_t len)
|
||||
{
|
||||
/* silently ignore RRs over the limit */
|
||||
if(d->numhttps_rrs < DOH_MAX_HTTPS) {
|
||||
@@ -574,10 +583,8 @@ static DOHcode store_https(const unsigned char *doh,
|
||||
}
|
||||
#endif
|
||||
|
||||
static DOHcode store_cname(const unsigned char *doh,
|
||||
size_t dohlen,
|
||||
unsigned int index,
|
||||
struct dohentry *d)
|
||||
static DOHcode doh_store_cname(const unsigned char *doh, size_t dohlen,
|
||||
unsigned int index, struct dohentry *d)
|
||||
{
|
||||
struct dynbuf *c;
|
||||
unsigned int loop = 128; /* a valid DNS name can never loop this much */
|
||||
@@ -626,12 +633,12 @@ static DOHcode store_cname(const unsigned char *doh,
|
||||
return DOH_OK;
|
||||
}
|
||||
|
||||
static DOHcode rdata(const unsigned char *doh,
|
||||
size_t dohlen,
|
||||
unsigned short rdlength,
|
||||
unsigned short type,
|
||||
int index,
|
||||
struct dohentry *d)
|
||||
static DOHcode doh_rdata(const unsigned char *doh,
|
||||
size_t dohlen,
|
||||
unsigned short rdlength,
|
||||
unsigned short type,
|
||||
int index,
|
||||
struct dohentry *d)
|
||||
{
|
||||
/* RDATA
|
||||
- A (TYPE 1): 4 bytes
|
||||
@@ -644,26 +651,22 @@ static DOHcode rdata(const unsigned char *doh,
|
||||
case DNS_TYPE_A:
|
||||
if(rdlength != 4)
|
||||
return DOH_DNS_RDATA_LEN;
|
||||
rc = store_a(doh, index, d);
|
||||
if(rc)
|
||||
return rc;
|
||||
doh_store_a(doh, index, d);
|
||||
break;
|
||||
case DNS_TYPE_AAAA:
|
||||
if(rdlength != 16)
|
||||
return DOH_DNS_RDATA_LEN;
|
||||
rc = store_aaaa(doh, index, d);
|
||||
if(rc)
|
||||
return rc;
|
||||
doh_store_aaaa(doh, index, d);
|
||||
break;
|
||||
#ifdef USE_HTTPSRR
|
||||
case DNS_TYPE_HTTPS:
|
||||
rc = store_https(doh, index, d, rdlength);
|
||||
rc = doh_store_https(doh, index, d, rdlength);
|
||||
if(rc)
|
||||
return rc;
|
||||
break;
|
||||
#endif
|
||||
case DNS_TYPE_CNAME:
|
||||
rc = store_cname(doh, dohlen, (unsigned int)index, d);
|
||||
rc = doh_store_cname(doh, dohlen, (unsigned int)index, d);
|
||||
if(rc)
|
||||
return rc;
|
||||
break;
|
||||
@@ -687,10 +690,10 @@ UNITTEST void de_init(struct dohentry *de)
|
||||
}
|
||||
|
||||
|
||||
UNITTEST DOHcode doh_decode(const unsigned char *doh,
|
||||
size_t dohlen,
|
||||
DNStype dnstype,
|
||||
struct dohentry *d)
|
||||
UNITTEST DOHcode doh_resp_decode(const unsigned char *doh,
|
||||
size_t dohlen,
|
||||
DNStype dnstype,
|
||||
struct dohentry *d)
|
||||
{
|
||||
unsigned char rcode;
|
||||
unsigned short qdcount;
|
||||
@@ -710,9 +713,9 @@ UNITTEST DOHcode doh_decode(const unsigned char *doh,
|
||||
if(rcode)
|
||||
return DOH_DNS_BAD_RCODE; /* bad rcode */
|
||||
|
||||
qdcount = get16bit(doh, 4);
|
||||
qdcount = doh_get16bit(doh, 4);
|
||||
while(qdcount) {
|
||||
rc = skipqname(doh, dohlen, &index);
|
||||
rc = doh_skipqname(doh, dohlen, &index);
|
||||
if(rc)
|
||||
return rc; /* bad qname */
|
||||
if(dohlen < (index + 4))
|
||||
@@ -721,19 +724,19 @@ UNITTEST DOHcode doh_decode(const unsigned char *doh,
|
||||
qdcount--;
|
||||
}
|
||||
|
||||
ancount = get16bit(doh, 6);
|
||||
ancount = doh_get16bit(doh, 6);
|
||||
while(ancount) {
|
||||
unsigned short class;
|
||||
unsigned int ttl;
|
||||
|
||||
rc = skipqname(doh, dohlen, &index);
|
||||
rc = doh_skipqname(doh, dohlen, &index);
|
||||
if(rc)
|
||||
return rc; /* bad qname */
|
||||
|
||||
if(dohlen < (index + 2))
|
||||
return DOH_DNS_OUT_OF_RANGE;
|
||||
|
||||
type = get16bit(doh, index);
|
||||
type = doh_get16bit(doh, index);
|
||||
if((type != DNS_TYPE_CNAME) /* may be synthesized from DNAME */
|
||||
&& (type != DNS_TYPE_DNAME) /* if present, accept and ignore */
|
||||
&& (type != dnstype))
|
||||
@@ -743,7 +746,7 @@ UNITTEST DOHcode doh_decode(const unsigned char *doh,
|
||||
|
||||
if(dohlen < (index + 2))
|
||||
return DOH_DNS_OUT_OF_RANGE;
|
||||
class = get16bit(doh, index);
|
||||
class = doh_get16bit(doh, index);
|
||||
if(DNS_CLASS_IN != class)
|
||||
return DOH_DNS_UNEXPECTED_CLASS; /* unsupported */
|
||||
index += 2;
|
||||
@@ -751,7 +754,7 @@ UNITTEST DOHcode doh_decode(const unsigned char *doh,
|
||||
if(dohlen < (index + 4))
|
||||
return DOH_DNS_OUT_OF_RANGE;
|
||||
|
||||
ttl = get32bit(doh, index);
|
||||
ttl = doh_get32bit(doh, index);
|
||||
if(ttl < d->ttl)
|
||||
d->ttl = ttl;
|
||||
index += 4;
|
||||
@@ -759,21 +762,21 @@ UNITTEST DOHcode doh_decode(const unsigned char *doh,
|
||||
if(dohlen < (index + 2))
|
||||
return DOH_DNS_OUT_OF_RANGE;
|
||||
|
||||
rdlength = get16bit(doh, index);
|
||||
rdlength = doh_get16bit(doh, index);
|
||||
index += 2;
|
||||
if(dohlen < (index + rdlength))
|
||||
return DOH_DNS_OUT_OF_RANGE;
|
||||
|
||||
rc = rdata(doh, dohlen, rdlength, type, (int)index, d);
|
||||
rc = doh_rdata(doh, dohlen, rdlength, type, (int)index, d);
|
||||
if(rc)
|
||||
return rc; /* bad rdata */
|
||||
return rc; /* bad doh_rdata */
|
||||
index += rdlength;
|
||||
ancount--;
|
||||
}
|
||||
|
||||
nscount = get16bit(doh, 8);
|
||||
nscount = doh_get16bit(doh, 8);
|
||||
while(nscount) {
|
||||
rc = skipqname(doh, dohlen, &index);
|
||||
rc = doh_skipqname(doh, dohlen, &index);
|
||||
if(rc)
|
||||
return rc; /* bad qname */
|
||||
|
||||
@@ -785,7 +788,7 @@ UNITTEST DOHcode doh_decode(const unsigned char *doh,
|
||||
if(dohlen < (index + 2))
|
||||
return DOH_DNS_OUT_OF_RANGE;
|
||||
|
||||
rdlength = get16bit(doh, index);
|
||||
rdlength = doh_get16bit(doh, index);
|
||||
index += 2;
|
||||
if(dohlen < (index + rdlength))
|
||||
return DOH_DNS_OUT_OF_RANGE;
|
||||
@@ -793,9 +796,9 @@ UNITTEST DOHcode doh_decode(const unsigned char *doh,
|
||||
nscount--;
|
||||
}
|
||||
|
||||
arcount = get16bit(doh, 10);
|
||||
arcount = doh_get16bit(doh, 10);
|
||||
while(arcount) {
|
||||
rc = skipqname(doh, dohlen, &index);
|
||||
rc = doh_skipqname(doh, dohlen, &index);
|
||||
if(rc)
|
||||
return rc; /* bad qname */
|
||||
|
||||
@@ -807,7 +810,7 @@ UNITTEST DOHcode doh_decode(const unsigned char *doh,
|
||||
if(dohlen < (index + 2))
|
||||
return DOH_DNS_OUT_OF_RANGE;
|
||||
|
||||
rdlength = get16bit(doh, index);
|
||||
rdlength = doh_get16bit(doh, index);
|
||||
index += 2;
|
||||
if(dohlen < (index + rdlength))
|
||||
return DOH_DNS_OUT_OF_RANGE;
|
||||
@@ -830,8 +833,8 @@ UNITTEST DOHcode doh_decode(const unsigned char *doh,
|
||||
}
|
||||
|
||||
#ifndef CURL_DISABLE_VERBOSE_STRINGS
|
||||
static void showdoh(struct Curl_easy *data,
|
||||
const struct dohentry *d)
|
||||
static void doh_show(struct Curl_easy *data,
|
||||
const struct dohentry *d)
|
||||
{
|
||||
int i;
|
||||
infof(data, "[DoH] TTL: %u seconds", d->ttl);
|
||||
@@ -864,8 +867,8 @@ static void showdoh(struct Curl_easy *data,
|
||||
#ifdef USE_HTTPSRR
|
||||
for(i = 0; i < d->numhttps_rrs; i++) {
|
||||
# ifdef DEBUGBUILD
|
||||
local_print_buf(data, "DoH HTTPS",
|
||||
d->https_rrs[i].val, d->https_rrs[i].len);
|
||||
doh_print_buf(data, "DoH HTTPS",
|
||||
d->https_rrs[i].val, d->https_rrs[i].len);
|
||||
# else
|
||||
infof(data, "DoH HTTPS RR: length %d", d->https_rrs[i].len);
|
||||
# endif
|
||||
@@ -876,7 +879,7 @@ static void showdoh(struct Curl_easy *data,
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define showdoh(x,y)
|
||||
#define doh_show(x,y)
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -996,7 +999,7 @@ static CURLcode doh2ai(const struct dohentry *de, const char *hostname,
|
||||
}
|
||||
|
||||
#ifndef CURL_DISABLE_VERBOSE_STRINGS
|
||||
static const char *type2name(DNStype dnstype)
|
||||
static const char *doh_type2name(DNStype dnstype)
|
||||
{
|
||||
switch(dnstype) {
|
||||
case DNS_TYPE_A:
|
||||
@@ -1041,8 +1044,8 @@ UNITTEST void de_cleanup(struct dohentry *d)
|
||||
* just after the end of the DNS name encoding on output. (And
|
||||
* that is why it is an "unsigned char **" :-)
|
||||
*/
|
||||
static CURLcode local_decode_rdata_name(unsigned char **buf, size_t *remaining,
|
||||
char **dnsname)
|
||||
static CURLcode doh_decode_rdata_name(unsigned char **buf, size_t *remaining,
|
||||
char **dnsname)
|
||||
{
|
||||
unsigned char *cp = NULL;
|
||||
int rem = 0;
|
||||
@@ -1088,8 +1091,8 @@ static CURLcode local_decode_rdata_name(unsigned char **buf, size_t *remaining,
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static CURLcode local_decode_rdata_alpn(unsigned char *rrval, size_t len,
|
||||
char **alpns)
|
||||
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
|
||||
@@ -1145,7 +1148,7 @@ err:
|
||||
}
|
||||
|
||||
#ifdef DEBUGBUILD
|
||||
static CURLcode test_alpn_escapes(void)
|
||||
static CURLcode doh_test_alpn_escapes(void)
|
||||
{
|
||||
/* we will use an example from draft-ietf-dnsop-svcb, figure 10 */
|
||||
static unsigned char example[] = {
|
||||
@@ -1158,7 +1161,7 @@ static CURLcode test_alpn_escapes(void)
|
||||
char *aval = NULL;
|
||||
static const char *expected = "f\\\\oo\\,bar,h2";
|
||||
|
||||
if(local_decode_rdata_alpn(example, example_len, &aval) != CURLE_OK)
|
||||
if(doh_decode_rdata_alpn(example, example_len, &aval) != CURLE_OK)
|
||||
return CURLE_BAD_CONTENT_ENCODING;
|
||||
if(strlen(aval) != strlen(expected))
|
||||
return CURLE_BAD_CONTENT_ENCODING;
|
||||
@@ -1168,7 +1171,7 @@ static CURLcode test_alpn_escapes(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
static CURLcode Curl_doh_decode_httpsrr(unsigned char *rrval, size_t len,
|
||||
static CURLcode doh_resp_decode_httpsrr(unsigned char *rrval, size_t len,
|
||||
struct Curl_https_rrinfo **hrr)
|
||||
{
|
||||
size_t remaining = len;
|
||||
@@ -1179,7 +1182,7 @@ static CURLcode Curl_doh_decode_httpsrr(unsigned char *rrval, size_t len,
|
||||
|
||||
#ifdef DEBUGBUILD
|
||||
/* a few tests of escaping, should not be here but ok for now */
|
||||
if(test_alpn_escapes() != CURLE_OK)
|
||||
if(doh_test_alpn_escapes() != CURLE_OK)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
#endif
|
||||
lhrr = calloc(1, sizeof(struct Curl_https_rrinfo));
|
||||
@@ -1194,7 +1197,7 @@ static CURLcode Curl_doh_decode_httpsrr(unsigned char *rrval, size_t len,
|
||||
lhrr->priority = (uint16_t)((cp[0] << 8) + cp[1]);
|
||||
cp += 2;
|
||||
remaining -= (uint16_t)2;
|
||||
if(local_decode_rdata_name(&cp, &remaining, &dnsname) != CURLE_OK)
|
||||
if(doh_decode_rdata_name(&cp, &remaining, &dnsname) != CURLE_OK)
|
||||
goto err;
|
||||
lhrr->target = dnsname;
|
||||
while(remaining >= 4) {
|
||||
@@ -1204,7 +1207,7 @@ static CURLcode Curl_doh_decode_httpsrr(unsigned char *rrval, size_t len,
|
||||
cp += 2;
|
||||
remaining -= 4;
|
||||
if(pcode == HTTPS_RR_CODE_ALPN) {
|
||||
if(local_decode_rdata_alpn(cp, plen, &lhrr->alpns) != CURLE_OK)
|
||||
if(doh_decode_rdata_alpn(cp, plen, &lhrr->alpns) != CURLE_OK)
|
||||
goto err;
|
||||
}
|
||||
if(pcode == HTTPS_RR_CODE_NO_DEF_ALPN)
|
||||
@@ -1253,8 +1256,8 @@ err:
|
||||
}
|
||||
|
||||
# ifdef DEBUGBUILD
|
||||
static void local_print_httpsrr(struct Curl_easy *data,
|
||||
struct Curl_https_rrinfo *hrr)
|
||||
static void doh_print_httpsrr(struct Curl_easy *data,
|
||||
struct Curl_https_rrinfo *hrr)
|
||||
{
|
||||
DEBUGASSERT(hrr);
|
||||
infof(data, "HTTPS RR: priority %d, target: %s",
|
||||
@@ -1268,20 +1271,20 @@ static void local_print_httpsrr(struct Curl_easy *data,
|
||||
else
|
||||
infof(data, "HTTPS RR: no_def_alpn not set");
|
||||
if(hrr->ipv4hints) {
|
||||
local_print_buf(data, "HTTPS RR: ipv4hints",
|
||||
hrr->ipv4hints, hrr->ipv4hints_len);
|
||||
doh_print_buf(data, "HTTPS RR: ipv4hints",
|
||||
hrr->ipv4hints, hrr->ipv4hints_len);
|
||||
}
|
||||
else
|
||||
infof(data, "HTTPS RR: no ipv4hints");
|
||||
if(hrr->echconfiglist) {
|
||||
local_print_buf(data, "HTTPS RR: ECHConfigList",
|
||||
hrr->echconfiglist, hrr->echconfiglist_len);
|
||||
doh_print_buf(data, "HTTPS RR: ECHConfigList",
|
||||
hrr->echconfiglist, hrr->echconfiglist_len);
|
||||
}
|
||||
else
|
||||
infof(data, "HTTPS RR: no ECHConfigList");
|
||||
if(hrr->ipv6hints) {
|
||||
local_print_buf(data, "HTTPS RR: ipv6hint",
|
||||
hrr->ipv6hints, hrr->ipv6hints_len);
|
||||
doh_print_buf(data, "HTTPS RR: ipv6hint",
|
||||
hrr->ipv6hints, hrr->ipv6hints_len);
|
||||
}
|
||||
else
|
||||
infof(data, "HTTPS RR: no ipv6hints");
|
||||
@@ -1294,52 +1297,45 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
|
||||
struct Curl_dns_entry **dnsp)
|
||||
{
|
||||
CURLcode result;
|
||||
struct dohdata *dohp = data->req.doh;
|
||||
struct doh_probes *dohp = data->req.doh;
|
||||
*dnsp = NULL; /* defaults to no response */
|
||||
if(!dohp)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
if(!dohp->probe[DOH_PROBE_SLOT_IPADDR_V4].easy &&
|
||||
!dohp->probe[DOH_PROBE_SLOT_IPADDR_V6].easy) {
|
||||
if(dohp->probe[DOH_SLOT_IPV4].easy_mid < 0 &&
|
||||
dohp->probe[DOH_SLOT_IPV6].easy_mid < 0) {
|
||||
failf(data, "Could not DoH-resolve: %s", data->state.async.hostname);
|
||||
return CONN_IS_PROXIED(data->conn)?CURLE_COULDNT_RESOLVE_PROXY:
|
||||
CURLE_COULDNT_RESOLVE_HOST;
|
||||
}
|
||||
else if(!dohp->pending) {
|
||||
#ifndef USE_HTTPSRR
|
||||
DOHcode rc[DOH_PROBE_SLOTS] = {
|
||||
DOH_OK, DOH_OK
|
||||
};
|
||||
#else
|
||||
DOHcode rc[DOH_PROBE_SLOTS] = {
|
||||
DOH_OK, DOH_OK, DOH_OK
|
||||
};
|
||||
#endif
|
||||
DOHcode rc[DOH_SLOT_COUNT];
|
||||
struct dohentry de;
|
||||
int slot;
|
||||
|
||||
memset(rc, 0, sizeof(rc));
|
||||
/* remove DoH handles from multi handle and close them */
|
||||
Curl_doh_close(data);
|
||||
/* parse the responses, create the struct and return it! */
|
||||
de_init(&de);
|
||||
for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) {
|
||||
struct dnsprobe *p = &dohp->probe[slot];
|
||||
for(slot = 0; slot < DOH_SLOT_COUNT; slot++) {
|
||||
struct doh_probe *p = &dohp->probe[slot];
|
||||
if(!p->dnstype)
|
||||
continue;
|
||||
rc[slot] = doh_decode(Curl_dyn_uptr(&p->serverdoh),
|
||||
Curl_dyn_len(&p->serverdoh),
|
||||
p->dnstype,
|
||||
&de);
|
||||
Curl_dyn_free(&p->serverdoh);
|
||||
rc[slot] = doh_resp_decode(Curl_dyn_uptr(&p->resp_body),
|
||||
Curl_dyn_len(&p->resp_body),
|
||||
p->dnstype, &de);
|
||||
Curl_dyn_free(&p->resp_body);
|
||||
#ifndef CURL_DISABLE_VERBOSE_STRINGS
|
||||
if(rc[slot]) {
|
||||
infof(data, "DoH: %s type %s for %s", doh_strerror(rc[slot]),
|
||||
type2name(p->dnstype), dohp->host);
|
||||
doh_type2name(p->dnstype), dohp->host);
|
||||
}
|
||||
#endif
|
||||
} /* next slot */
|
||||
|
||||
result = CURLE_COULDNT_RESOLVE_HOST; /* until we know better */
|
||||
if(!rc[DOH_PROBE_SLOT_IPADDR_V4] || !rc[DOH_PROBE_SLOT_IPADDR_V6]) {
|
||||
if(!rc[DOH_SLOT_IPV4] || !rc[DOH_SLOT_IPV6]) {
|
||||
/* we have an address, of one kind or other */
|
||||
struct Curl_dns_entry *dns;
|
||||
struct Curl_addrinfo *ai;
|
||||
@@ -1347,7 +1343,7 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
|
||||
|
||||
if(Curl_trc_ft_is_verbose(data, &Curl_doh_trc)) {
|
||||
infof(data, "[DoH] hostname: %s", dohp->host);
|
||||
showdoh(data, &de);
|
||||
doh_show(data, &de);
|
||||
}
|
||||
|
||||
result = doh2ai(&de, dohp->host, dohp->port, &ai);
|
||||
@@ -1360,7 +1356,7 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
|
||||
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
|
||||
|
||||
/* we got a response, store it in the cache */
|
||||
dns = Curl_cache_addr(data, ai, dohp->host, 0, dohp->port);
|
||||
dns = Curl_cache_addr(data, ai, dohp->host, 0, dohp->port, FALSE);
|
||||
|
||||
if(data->share)
|
||||
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
|
||||
@@ -1380,7 +1376,7 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
|
||||
#ifdef USE_HTTPSRR
|
||||
if(de.numhttps_rrs > 0 && result == CURLE_OK && *dnsp) {
|
||||
struct Curl_https_rrinfo *hrr = NULL;
|
||||
result = Curl_doh_decode_httpsrr(de.https_rrs->val, de.https_rrs->len,
|
||||
result = doh_resp_decode_httpsrr(de.https_rrs->val, de.https_rrs->len,
|
||||
&hrr);
|
||||
if(result) {
|
||||
infof(data, "Failed to decode HTTPS RR");
|
||||
@@ -1388,7 +1384,7 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
|
||||
}
|
||||
infof(data, "Some HTTPS RR to process");
|
||||
# ifdef DEBUGBUILD
|
||||
local_print_httpsrr(data, hrr);
|
||||
doh_print_httpsrr(data, hrr);
|
||||
# endif
|
||||
(*dnsp)->hinfo = hrr;
|
||||
}
|
||||
@@ -1396,7 +1392,7 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
|
||||
|
||||
/* All done */
|
||||
de_cleanup(&de);
|
||||
Curl_safefree(data->req.doh);
|
||||
Curl_doh_cleanup(data);
|
||||
return result;
|
||||
|
||||
} /* !dohp->pending */
|
||||
@@ -1407,28 +1403,39 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
|
||||
|
||||
void Curl_doh_close(struct Curl_easy *data)
|
||||
{
|
||||
struct dohdata *doh = data->req.doh;
|
||||
if(doh) {
|
||||
struct doh_probes *doh = data->req.doh;
|
||||
if(doh && data->multi) {
|
||||
struct Curl_easy *probe_data;
|
||||
curl_off_t mid;
|
||||
size_t slot;
|
||||
for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) {
|
||||
if(!doh->probe[slot].easy)
|
||||
for(slot = 0; slot < DOH_SLOT_COUNT; slot++) {
|
||||
mid = doh->probe[slot].easy_mid;
|
||||
if(mid < 0)
|
||||
continue;
|
||||
doh->probe[slot].easy_mid = -1;
|
||||
/* should have been called before data is removed from multi handle */
|
||||
DEBUGASSERT(data->multi);
|
||||
probe_data = data->multi? Curl_multi_get_handle(data->multi, mid) : NULL;
|
||||
if(!probe_data) {
|
||||
DEBUGF(infof(data, "Curl_doh_close: xfer for mid=%"
|
||||
FMT_OFF_T " not found!",
|
||||
doh->probe[slot].easy_mid));
|
||||
continue;
|
||||
}
|
||||
/* data->multi might already be reset at this time */
|
||||
if(doh->probe[slot].easy->multi)
|
||||
curl_multi_remove_handle(doh->probe[slot].easy->multi,
|
||||
doh->probe[slot].easy);
|
||||
Curl_close(&doh->probe[slot].easy);
|
||||
curl_multi_remove_handle(data->multi, probe_data);
|
||||
Curl_close(&probe_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Curl_doh_cleanup(struct Curl_easy *data)
|
||||
{
|
||||
struct dohdata *doh = data->req.doh;
|
||||
struct doh_probes *doh = data->req.doh;
|
||||
if(doh) {
|
||||
Curl_doh_close(data);
|
||||
curl_slist_free_all(doh->headers);
|
||||
data->req.doh->headers = NULL;
|
||||
curl_slist_free_all(doh->req_hds);
|
||||
data->req.doh->req_hds = NULL;
|
||||
Curl_safefree(data->req.doh);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,18 +59,39 @@ typedef enum {
|
||||
} DNStype;
|
||||
|
||||
/* one of these for each DoH request */
|
||||
struct dnsprobe {
|
||||
CURL *easy;
|
||||
struct doh_probe {
|
||||
curl_off_t easy_mid; /* multi id of easy handle doing the lookup */
|
||||
DNStype dnstype;
|
||||
unsigned char dohbuffer[512];
|
||||
size_t dohlen;
|
||||
struct dynbuf serverdoh;
|
||||
unsigned char req_body[512];
|
||||
size_t req_body_len;
|
||||
struct dynbuf resp_body;
|
||||
};
|
||||
|
||||
struct dohdata {
|
||||
struct curl_slist *headers;
|
||||
struct dnsprobe probe[DOH_PROBE_SLOTS];
|
||||
unsigned int pending; /* still outstanding requests */
|
||||
enum doh_slot_num {
|
||||
/* Explicit values for first two symbols so as to match hard-coded
|
||||
* constants in existing code
|
||||
*/
|
||||
DOH_SLOT_IPV4 = 0, /* make 'V4' stand out for readability */
|
||||
DOH_SLOT_IPV6 = 1, /* 'V6' likewise */
|
||||
|
||||
/* Space here for (possibly build-specific) additional slot definitions */
|
||||
#ifdef USE_HTTPSRR
|
||||
DOH_SLOT_HTTPS_RR = 2, /* for HTTPS RR */
|
||||
#endif
|
||||
|
||||
/* for example */
|
||||
/* #ifdef WANT_DOH_FOOBAR_TXT */
|
||||
/* DOH_PROBE_SLOT_FOOBAR_TXT, */
|
||||
/* #endif */
|
||||
|
||||
/* AFTER all slot definitions, establish how many we have */
|
||||
DOH_SLOT_COUNT
|
||||
};
|
||||
|
||||
struct doh_probes {
|
||||
struct curl_slist *req_hds;
|
||||
struct doh_probe probe[DOH_SLOT_COUNT];
|
||||
unsigned int pending; /* still outstanding probes */
|
||||
int port;
|
||||
const char *host;
|
||||
};
|
||||
@@ -116,7 +137,7 @@ struct dohaddr {
|
||||
#define HTTPS_RR_CODE_IPV6 0x06
|
||||
|
||||
/*
|
||||
* These may need escaping when found within an alpn string
|
||||
* These may need escaping when found within an ALPN string
|
||||
* value.
|
||||
*/
|
||||
#define COMMA_CHAR ','
|
||||
@@ -144,15 +165,15 @@ void Curl_doh_close(struct Curl_easy *data);
|
||||
void Curl_doh_cleanup(struct Curl_easy *data);
|
||||
|
||||
#ifdef UNITTESTS
|
||||
UNITTEST DOHcode doh_encode(const char *host,
|
||||
DNStype dnstype,
|
||||
unsigned char *dnsp, /* buffer */
|
||||
size_t len, /* buffer size */
|
||||
size_t *olen); /* output length */
|
||||
UNITTEST DOHcode doh_decode(const unsigned char *doh,
|
||||
size_t dohlen,
|
||||
DNStype dnstype,
|
||||
struct dohentry *d);
|
||||
UNITTEST DOHcode doh_req_encode(const char *host,
|
||||
DNStype dnstype,
|
||||
unsigned char *dnsp, /* buffer */
|
||||
size_t len, /* buffer size */
|
||||
size_t *olen); /* output length */
|
||||
UNITTEST DOHcode doh_resp_decode(const unsigned char *doh,
|
||||
size_t dohlen,
|
||||
DNStype dnstype,
|
||||
struct dohentry *d);
|
||||
|
||||
UNITTEST void de_init(struct dohentry *d);
|
||||
UNITTEST void de_cleanup(struct dohentry *d);
|
||||
|
||||
+70
-89
@@ -113,6 +113,7 @@ static curl_simple_lock s_lock = CURL_SIMPLE_LOCK_INIT;
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && defined(_DLL)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4232) /* MSVC extension, dllimport identity */
|
||||
#endif
|
||||
|
||||
@@ -130,7 +131,7 @@ curl_wcsdup_callback Curl_cwcsdup = Curl_wcsdup;
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && defined(_DLL)
|
||||
# pragma warning(default:4232) /* MSVC extension, dllimport identity */
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#ifdef DEBUGBUILD
|
||||
@@ -390,25 +391,22 @@ struct events {
|
||||
int running_handles; /* store the returned number */
|
||||
};
|
||||
|
||||
#define DEBUG_EV_POLL 0
|
||||
|
||||
/* events_timer
|
||||
*
|
||||
* Callback that gets called with a new value when the timeout should be
|
||||
* updated.
|
||||
*/
|
||||
|
||||
static int events_timer(struct Curl_multi *multi, /* multi handle */
|
||||
long timeout_ms, /* see above */
|
||||
void *userp) /* private callback pointer */
|
||||
{
|
||||
struct events *ev = userp;
|
||||
(void)multi;
|
||||
if(timeout_ms == -1)
|
||||
/* timeout removed */
|
||||
timeout_ms = 0;
|
||||
else if(timeout_ms == 0)
|
||||
/* timeout is already reached! */
|
||||
timeout_ms = 1; /* trigger asap */
|
||||
|
||||
#if DEBUG_EV_POLL
|
||||
fprintf(stderr, "events_timer: set timeout %ldms\n", timeout_ms);
|
||||
#endif
|
||||
ev->ms = timeout_ms;
|
||||
ev->msbump = TRUE;
|
||||
return 0;
|
||||
@@ -462,6 +460,7 @@ static int events_socket(struct Curl_easy *easy, /* easy handle */
|
||||
struct events *ev = userp;
|
||||
struct socketmonitor *m;
|
||||
struct socketmonitor *prev = NULL;
|
||||
bool found = FALSE;
|
||||
|
||||
#if defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
(void) easy;
|
||||
@@ -471,7 +470,7 @@ static int events_socket(struct Curl_easy *easy, /* easy handle */
|
||||
m = ev->list;
|
||||
while(m) {
|
||||
if(m->socket.fd == s) {
|
||||
|
||||
found = TRUE;
|
||||
if(what == CURL_POLL_REMOVE) {
|
||||
struct socketmonitor *nxt = m->next;
|
||||
/* remove this node from the list of monitored sockets */
|
||||
@@ -480,15 +479,13 @@ static int events_socket(struct Curl_easy *easy, /* easy handle */
|
||||
else
|
||||
ev->list = nxt;
|
||||
free(m);
|
||||
m = nxt;
|
||||
infof(easy, "socket cb: socket %" CURL_FORMAT_SOCKET_T
|
||||
" REMOVED", s);
|
||||
infof(easy, "socket cb: socket %" FMT_SOCKET_T " REMOVED", s);
|
||||
}
|
||||
else {
|
||||
/* The socket 's' is already being monitored, update the activity
|
||||
mask. Convert from libcurl bitmask to the poll one. */
|
||||
m->socket.events = socketcb2poll(what);
|
||||
infof(easy, "socket cb: socket %" CURL_FORMAT_SOCKET_T
|
||||
infof(easy, "socket cb: socket %" FMT_SOCKET_T
|
||||
" UPDATED as %s%s", s,
|
||||
(what&CURL_POLL_IN)?"IN":"",
|
||||
(what&CURL_POLL_OUT)?"OUT":"");
|
||||
@@ -498,12 +495,13 @@ static int events_socket(struct Curl_easy *easy, /* easy handle */
|
||||
prev = m;
|
||||
m = m->next; /* move to next node */
|
||||
}
|
||||
if(!m) {
|
||||
|
||||
if(!found) {
|
||||
if(what == CURL_POLL_REMOVE) {
|
||||
/* this happens a bit too often, libcurl fix perhaps? */
|
||||
/* fprintf(stderr,
|
||||
"%s: socket %d asked to be REMOVED but not present!\n",
|
||||
__func__, s); */
|
||||
/* should not happen if our logic is correct, but is no drama. */
|
||||
DEBUGF(infof(easy, "socket cb: asked to REMOVE socket %"
|
||||
FMT_SOCKET_T "but not present!", s));
|
||||
DEBUGASSERT(0);
|
||||
}
|
||||
else {
|
||||
m = malloc(sizeof(struct socketmonitor));
|
||||
@@ -513,8 +511,7 @@ static int events_socket(struct Curl_easy *easy, /* easy handle */
|
||||
m->socket.events = socketcb2poll(what);
|
||||
m->socket.revents = 0;
|
||||
ev->list = m;
|
||||
infof(easy, "socket cb: socket %" CURL_FORMAT_SOCKET_T
|
||||
" ADDED as %s%s", s,
|
||||
infof(easy, "socket cb: socket %" FMT_SOCKET_T " ADDED as %s%s", s,
|
||||
(what&CURL_POLL_IN)?"IN":"",
|
||||
(what&CURL_POLL_OUT)?"OUT":"");
|
||||
}
|
||||
@@ -564,14 +561,15 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
|
||||
int pollrc;
|
||||
int i;
|
||||
struct curltime before;
|
||||
struct curltime after;
|
||||
|
||||
/* populate the fds[] array */
|
||||
for(m = ev->list, f = &fds[0]; m; m = m->next) {
|
||||
f->fd = m->socket.fd;
|
||||
f->events = m->socket.events;
|
||||
f->revents = 0;
|
||||
/* fprintf(stderr, "poll() %d check socket %d\n", numfds, f->fd); */
|
||||
#if DEBUG_EV_POLL
|
||||
fprintf(stderr, "poll() %d check socket %d\n", numfds, f->fd);
|
||||
#endif
|
||||
f++;
|
||||
numfds++;
|
||||
}
|
||||
@@ -579,12 +577,27 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
|
||||
/* get the time stamp to use to figure out how long poll takes */
|
||||
before = Curl_now();
|
||||
|
||||
/* wait for activity or timeout */
|
||||
pollrc = Curl_poll(fds, (unsigned int)numfds, ev->ms);
|
||||
if(pollrc < 0)
|
||||
return CURLE_UNRECOVERABLE_POLL;
|
||||
|
||||
after = Curl_now();
|
||||
if(numfds) {
|
||||
/* wait for activity or timeout */
|
||||
#if DEBUG_EV_POLL
|
||||
fprintf(stderr, "poll(numfds=%d, timeout=%ldms)\n", numfds, ev->ms);
|
||||
#endif
|
||||
pollrc = Curl_poll(fds, (unsigned int)numfds, ev->ms);
|
||||
#if DEBUG_EV_POLL
|
||||
fprintf(stderr, "poll(numfds=%d, timeout=%ldms) -> %d\n",
|
||||
numfds, ev->ms, pollrc);
|
||||
#endif
|
||||
if(pollrc < 0)
|
||||
return CURLE_UNRECOVERABLE_POLL;
|
||||
}
|
||||
else {
|
||||
#if DEBUG_EV_POLL
|
||||
fprintf(stderr, "poll, but no fds, wait timeout=%ldms\n", ev->ms);
|
||||
#endif
|
||||
pollrc = 0;
|
||||
if(ev->ms > 0)
|
||||
Curl_wait_ms(ev->ms);
|
||||
}
|
||||
|
||||
ev->msbump = FALSE; /* reset here */
|
||||
|
||||
@@ -597,26 +610,37 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
|
||||
}
|
||||
else {
|
||||
/* here pollrc is > 0 */
|
||||
struct Curl_llist_node *e = Curl_llist_head(&multi->process);
|
||||
struct Curl_easy *data;
|
||||
DEBUGASSERT(e);
|
||||
data = Curl_node_elem(e);
|
||||
DEBUGASSERT(data);
|
||||
|
||||
/* loop over the monitored sockets to see which ones had activity */
|
||||
for(i = 0; i< numfds; i++) {
|
||||
if(fds[i].revents) {
|
||||
/* socket activity, tell libcurl */
|
||||
int act = poll2cselect(fds[i].revents); /* convert */
|
||||
infof(multi->easyp,
|
||||
"call curl_multi_socket_action(socket "
|
||||
"%" CURL_FORMAT_SOCKET_T ")", fds[i].fd);
|
||||
|
||||
/* sending infof "randomly" to the first easy handle */
|
||||
infof(data, "call curl_multi_socket_action(socket "
|
||||
"%" FMT_SOCKET_T ")", (curl_socket_t)fds[i].fd);
|
||||
mcode = curl_multi_socket_action(multi, fds[i].fd, act,
|
||||
&ev->running_handles);
|
||||
}
|
||||
}
|
||||
|
||||
if(!ev->msbump) {
|
||||
|
||||
if(!ev->msbump && ev->ms >= 0) {
|
||||
/* If nothing updated the timeout, we decrease it by the spent time.
|
||||
* If it was updated, it has the new timeout time stored already.
|
||||
*/
|
||||
timediff_t timediff = Curl_timediff(after, before);
|
||||
timediff_t timediff = Curl_timediff(Curl_now(), before);
|
||||
if(timediff > 0) {
|
||||
#if DEBUG_EV_POLL
|
||||
fprintf(stderr, "poll timeout %ldms not updated, decrease by "
|
||||
"time spent %ldms\n", ev->ms, (long)timediff);
|
||||
#endif
|
||||
if(timediff > ev->ms)
|
||||
ev->ms = 0;
|
||||
else
|
||||
@@ -649,7 +673,7 @@ static CURLcode easy_events(struct Curl_multi *multi)
|
||||
{
|
||||
/* this struct is made static to allow it to be used after this function
|
||||
returns and curl_multi_remove_handle() is called */
|
||||
static struct events evs = {2, FALSE, 0, NULL, 0};
|
||||
static struct events evs = {-1, FALSE, 0, NULL, 0};
|
||||
|
||||
/* if running event-based, do some further multi inits */
|
||||
events_setup(multi, &evs);
|
||||
@@ -914,8 +938,7 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
|
||||
|
||||
Curl_dyn_init(&outcurl->state.headerb, CURL_MAX_HTTP_HEADER);
|
||||
|
||||
/* the connection cache is setup on demand */
|
||||
outcurl->state.conn_cache = NULL;
|
||||
/* the connection pool is setup on demand */
|
||||
outcurl->state.lastconnect_id = -1;
|
||||
outcurl->state.recent_conn_id = -1;
|
||||
outcurl->id = -1;
|
||||
@@ -1012,7 +1035,9 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
|
||||
goto fail;
|
||||
}
|
||||
#endif /* USE_ARES */
|
||||
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
Curl_llist_init(&outcurl->state.httphdrs, NULL);
|
||||
#endif
|
||||
Curl_initinfo(outcurl);
|
||||
|
||||
outcurl->magic = CURLEASY_MAGIC_NUMBER;
|
||||
@@ -1112,7 +1137,7 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
|
||||
(data->mstate == MSTATE_PERFORMING ||
|
||||
data->mstate == MSTATE_RATELIMITING));
|
||||
/* Unpausing writes is detected on the next run in
|
||||
* transfer.c:Curl_readwrite(). This is because this may result
|
||||
* transfer.c:Curl_sendrecv(). This is because this may result
|
||||
* in a transfer error if the application's callbacks fail */
|
||||
|
||||
/* Set the new keepon state, so it takes effect no matter what error
|
||||
@@ -1264,7 +1289,7 @@ CURLcode Curl_senddata(struct Curl_easy *data, const void *buffer,
|
||||
Curl_attach_connection(data, c);
|
||||
|
||||
sigpipe_ignore(data, &pipe_st);
|
||||
result = Curl_conn_send(data, FIRSTSOCKET, buffer, buflen, n);
|
||||
result = Curl_conn_send(data, FIRSTSOCKET, buffer, buflen, FALSE, n);
|
||||
sigpipe_restore(&pipe_st);
|
||||
|
||||
if(result && result != CURLE_AGAIN)
|
||||
@@ -1289,47 +1314,6 @@ CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wrapper to call functions in Curl_conncache_foreach()
|
||||
*
|
||||
* Returns always 0.
|
||||
*/
|
||||
static int conn_upkeep(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
void *param)
|
||||
{
|
||||
struct curltime *now = param;
|
||||
|
||||
if(Curl_timediff(*now, conn->keepalive) <= data->set.upkeep_interval_ms)
|
||||
return 0;
|
||||
|
||||
/* briefly attach for action */
|
||||
Curl_attach_connection(data, conn);
|
||||
if(conn->handler->connection_check) {
|
||||
/* Do a protocol-specific keepalive check on the connection. */
|
||||
conn->handler->connection_check(data, conn, CONNCHECK_KEEPALIVE);
|
||||
}
|
||||
else {
|
||||
/* Do the generic action on the FIRSTSOCKET filter chain */
|
||||
Curl_conn_keep_alive(data, conn, FIRSTSOCKET);
|
||||
}
|
||||
Curl_detach_connection(data);
|
||||
|
||||
conn->keepalive = *now;
|
||||
return 0; /* continue iteration */
|
||||
}
|
||||
|
||||
static CURLcode upkeep(struct conncache *conn_cache, void *data)
|
||||
{
|
||||
struct curltime now = Curl_now();
|
||||
/* Loop over every connection and make connection alive. */
|
||||
Curl_conncache_foreach(data,
|
||||
conn_cache,
|
||||
&now,
|
||||
conn_upkeep);
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs connection upkeep for the given session handle.
|
||||
*/
|
||||
@@ -1339,12 +1323,9 @@ CURLcode curl_easy_upkeep(struct Curl_easy *data)
|
||||
if(!GOOD_EASY_HANDLE(data))
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
|
||||
if(data->multi_easy) {
|
||||
/* Use the common function to keep connections alive. */
|
||||
return upkeep(&data->multi_easy->conn_cache, data);
|
||||
}
|
||||
else {
|
||||
/* No connections, so just return success */
|
||||
return CURLE_OK;
|
||||
}
|
||||
if(Curl_is_in_callback(data))
|
||||
return CURLE_RECURSIVE_API_CALL;
|
||||
|
||||
/* Use the common function to keep connections alive. */
|
||||
return Curl_cpool_upkeep(data);
|
||||
}
|
||||
|
||||
+2
-2
@@ -63,12 +63,12 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string,
|
||||
if(!string || (inlength < 0))
|
||||
return NULL;
|
||||
|
||||
Curl_dyn_init(&d, CURL_MAX_INPUT_LENGTH * 3);
|
||||
|
||||
length = (inlength?(size_t)inlength:strlen(string));
|
||||
if(!length)
|
||||
return strdup("");
|
||||
|
||||
Curl_dyn_init(&d, length * 3 + 1);
|
||||
|
||||
while(length--) {
|
||||
/* treat the characters unsigned */
|
||||
unsigned char in = (unsigned char)*string++;
|
||||
|
||||
+2
-3
@@ -223,7 +223,7 @@ static CURLcode file_connect(struct Curl_easy *data, bool *done)
|
||||
* A leading slash in an AmigaDOS path denotes the parent
|
||||
* directory, and hence we block this as it is relative.
|
||||
* Absolute paths start with 'volumename:', so we check for
|
||||
* this first. Failing that, we treat the path as a real unix
|
||||
* this first. Failing that, we treat the path as a real Unix
|
||||
* path, but only if the application was compiled with -lunix.
|
||||
*/
|
||||
fd = -1;
|
||||
@@ -468,8 +468,7 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
|
||||
static const char accept_ranges[]= { "Accept-ranges: bytes\r\n" };
|
||||
if(expected_size >= 0) {
|
||||
headerlen =
|
||||
msnprintf(header, sizeof(header),
|
||||
"Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n",
|
||||
msnprintf(header, sizeof(header), "Content-Length: %" FMT_OFF_T "\r\n",
|
||||
expected_size);
|
||||
result = Curl_client_write(data, CLIENTWRITE_HEADER, header, headerlen);
|
||||
if(result)
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@
|
||||
|
||||
struct fileinfo {
|
||||
struct curl_fileinfo info;
|
||||
struct Curl_llist_element list;
|
||||
struct Curl_llist_node list;
|
||||
struct dynbuf buf;
|
||||
};
|
||||
|
||||
|
||||
+3
-3
@@ -790,10 +790,10 @@ static CURLcode setname(curl_mimepart *part, const char *name, size_t len)
|
||||
/* wrap call to fseeko so it matches the calling convention of callback */
|
||||
static int fseeko_wrapper(void *stream, curl_off_t offset, int whence)
|
||||
{
|
||||
#if defined(HAVE_FSEEKO) && defined(HAVE_DECL_FSEEKO)
|
||||
return fseeko(stream, (off_t)offset, whence);
|
||||
#elif defined(HAVE__FSEEKI64)
|
||||
#if defined(HAVE__FSEEKI64)
|
||||
return _fseeki64(stream, (__int64)offset, whence);
|
||||
#elif defined(HAVE_FSEEKO) && defined(HAVE_DECL_FSEEKO)
|
||||
return fseeko(stream, (off_t)offset, whence);
|
||||
#else
|
||||
if(offset > LONG_MAX)
|
||||
return -1;
|
||||
|
||||
@@ -188,7 +188,7 @@ static CURLcode ftp_regular_transfer(struct Curl_easy *data, bool *done);
|
||||
#ifndef CURL_DISABLE_VERBOSE_STRINGS
|
||||
static void ftp_pasv_verbose(struct Curl_easy *data,
|
||||
struct Curl_addrinfo *ai,
|
||||
char *newhost, /* ascii version */
|
||||
char *newhost, /* ASCII version */
|
||||
int port);
|
||||
#endif
|
||||
static CURLcode ftp_state_prepare_transfer(struct Curl_easy *data);
|
||||
@@ -327,7 +327,7 @@ static void freedirs(struct ftp_conn *ftpc)
|
||||
Curl_safefree(ftpc->newhost);
|
||||
}
|
||||
|
||||
#ifdef CURL_DO_LINEEND_CONV
|
||||
#ifdef CURL_PREFER_LF_LINEENDS
|
||||
/***********************************************************************
|
||||
*
|
||||
* Lineend Conversions
|
||||
@@ -369,7 +369,6 @@ static CURLcode ftp_cw_lc_write(struct Curl_easy *data,
|
||||
}
|
||||
/* either we just wrote the newline or it is part of the next
|
||||
* chunk of bytes we write. */
|
||||
data->state.crlf_conversions++;
|
||||
ctx->newline_pending = FALSE;
|
||||
}
|
||||
|
||||
@@ -400,7 +399,6 @@ static CURLcode ftp_cw_lc_write(struct Curl_easy *data,
|
||||
/* EndOfStream, if we have a trailing cr, now is the time to write it */
|
||||
if(ctx->newline_pending) {
|
||||
ctx->newline_pending = FALSE;
|
||||
data->state.crlf_conversions++;
|
||||
return Curl_cwriter_write(data, writer->next, type, &nl, 1);
|
||||
}
|
||||
/* Always pass on the EOS type indicator */
|
||||
@@ -418,7 +416,7 @@ static const struct Curl_cwtype ftp_cw_lc = {
|
||||
sizeof(struct ftp_cw_lc_ctx)
|
||||
};
|
||||
|
||||
#endif /* CURL_DO_LINEEND_CONV */
|
||||
#endif /* CURL_PREFER_LF_LINEENDS */
|
||||
/***********************************************************************
|
||||
*
|
||||
* AcceptServerConnect()
|
||||
@@ -819,6 +817,8 @@ CURLcode Curl_GetFTPResponse(struct Curl_easy *data,
|
||||
int cache_skip = 0;
|
||||
int value_to_be_ignored = 0;
|
||||
|
||||
CURL_TRC_FTP(data, "getFTPResponse start");
|
||||
|
||||
if(ftpcode)
|
||||
*ftpcode = 0; /* 0 for errors */
|
||||
else
|
||||
@@ -864,21 +864,27 @@ CURLcode Curl_GetFTPResponse(struct Curl_easy *data,
|
||||
*/
|
||||
}
|
||||
else if(!Curl_conn_data_pending(data, FIRSTSOCKET)) {
|
||||
switch(SOCKET_READABLE(sockfd, interval_ms)) {
|
||||
case -1: /* select() error, stop reading */
|
||||
curl_socket_t wsock = Curl_pp_needs_flush(data, pp)?
|
||||
sockfd : CURL_SOCKET_BAD;
|
||||
int ev = Curl_socket_check(sockfd, CURL_SOCKET_BAD, wsock, interval_ms);
|
||||
if(ev < 0) {
|
||||
failf(data, "FTP response aborted due to select/poll error: %d",
|
||||
SOCKERRNO);
|
||||
return CURLE_RECV_ERROR;
|
||||
|
||||
case 0: /* timeout */
|
||||
}
|
||||
else if(ev == 0) {
|
||||
if(Curl_pgrsUpdate(data))
|
||||
return CURLE_ABORTED_BY_CALLBACK;
|
||||
continue; /* just continue in our loop for the timeout duration */
|
||||
|
||||
default: /* for clarity */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(Curl_pp_needs_flush(data, pp)) {
|
||||
result = Curl_pp_flushsend(data, pp);
|
||||
if(result)
|
||||
break;
|
||||
}
|
||||
|
||||
result = ftp_readresp(data, FIRSTSOCKET, pp, ftpcode, &nread);
|
||||
if(result)
|
||||
break;
|
||||
@@ -897,6 +903,8 @@ CURLcode Curl_GetFTPResponse(struct Curl_easy *data,
|
||||
} /* while there is buffer left and loop is requested */
|
||||
|
||||
pp->pending_resp = FALSE;
|
||||
CURL_TRC_FTP(data, "getFTPResponse -> result=%d, nread=%zd, ftpcode=%d",
|
||||
result, *nreadp, *ftpcode);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1042,7 +1050,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
|
||||
int error;
|
||||
char *host = NULL;
|
||||
char *string_ftpport = data->set.str[STRING_FTPPORT];
|
||||
struct Curl_dns_entry *h = NULL;
|
||||
struct Curl_dns_entry *dns_entry = NULL;
|
||||
unsigned short port_min = 0;
|
||||
unsigned short port_max = 0;
|
||||
unsigned short port;
|
||||
@@ -1178,15 +1186,12 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
|
||||
}
|
||||
|
||||
/* resolv ip/host to ip */
|
||||
rc = Curl_resolv(data, host, 0, FALSE, &h);
|
||||
rc = Curl_resolv(data, host, 0, FALSE, &dns_entry);
|
||||
if(rc == CURLRESOLV_PENDING)
|
||||
(void)Curl_resolver_wait_resolv(data, &h);
|
||||
if(h) {
|
||||
res = h->addr;
|
||||
/* when we return from this function, we can forget about this entry
|
||||
to we can unlock it now already */
|
||||
Curl_resolv_unlock(data, h);
|
||||
} /* (h) */
|
||||
(void)Curl_resolver_wait_resolv(data, &dns_entry);
|
||||
if(dns_entry) {
|
||||
res = dns_entry->addr;
|
||||
}
|
||||
else
|
||||
res = NULL; /* failure! */
|
||||
|
||||
@@ -1381,6 +1386,9 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
|
||||
ftp_state(data, FTP_PORT);
|
||||
|
||||
out:
|
||||
/* If we looked up a dns_entry, now is the time to safely release it */
|
||||
if(dns_entry)
|
||||
Curl_resolv_unlink(data, &dns_entry);
|
||||
if(result) {
|
||||
ftp_state(data, FTP_STOP);
|
||||
}
|
||||
@@ -2072,7 +2080,6 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data,
|
||||
|
||||
/* postponed address resolution in case of tcp fastopen */
|
||||
if(conn->bits.tcp_fastopen && !conn->bits.reuse && !ftpc->newhost[0]) {
|
||||
Curl_conn_ev_update_info(data, conn);
|
||||
Curl_safefree(ftpc->newhost);
|
||||
ftpc->newhost = strdup(control_address(conn));
|
||||
if(!ftpc->newhost)
|
||||
@@ -2098,7 +2105,7 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data,
|
||||
CURL_CF_SSL_ENABLE : CURL_CF_SSL_DISABLE);
|
||||
|
||||
if(result) {
|
||||
Curl_resolv_unlock(data, addr); /* we are done using this address */
|
||||
Curl_resolv_unlink(data, &addr); /* we are done using this address */
|
||||
if(ftpc->count1 == 0 && ftpcode == 229)
|
||||
return ftp_epsv_disable(data, conn);
|
||||
|
||||
@@ -2116,7 +2123,7 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data,
|
||||
/* this just dumps information about this second connection */
|
||||
ftp_pasv_verbose(data, addr->addr, ftpc->newhost, connectport);
|
||||
|
||||
Curl_resolv_unlock(data, addr); /* we are done using this address */
|
||||
Curl_resolv_unlink(data, &addr); /* we are done using this address */
|
||||
|
||||
Curl_safefree(conn->secondaryhostname);
|
||||
conn->secondary_port = ftpc->newport;
|
||||
@@ -2383,8 +2390,8 @@ static CURLcode ftp_state_retr(struct Curl_easy *data,
|
||||
if(data->state.resume_from< 0) {
|
||||
/* We are supposed to download the last abs(from) bytes */
|
||||
if(filesize < -data->state.resume_from) {
|
||||
failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T
|
||||
") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")",
|
||||
failf(data, "Offset (%" FMT_OFF_T
|
||||
") was beyond file size (%" FMT_OFF_T ")",
|
||||
data->state.resume_from, filesize);
|
||||
return CURLE_BAD_DOWNLOAD_RESUME;
|
||||
}
|
||||
@@ -2395,8 +2402,8 @@ static CURLcode ftp_state_retr(struct Curl_easy *data,
|
||||
}
|
||||
else {
|
||||
if(filesize < data->state.resume_from) {
|
||||
failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T
|
||||
") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")",
|
||||
failf(data, "Offset (%" FMT_OFF_T
|
||||
") was beyond file size (%" FMT_OFF_T ")",
|
||||
data->state.resume_from, filesize);
|
||||
return CURLE_BAD_DOWNLOAD_RESUME;
|
||||
}
|
||||
@@ -2418,10 +2425,10 @@ static CURLcode ftp_state_retr(struct Curl_easy *data,
|
||||
}
|
||||
|
||||
/* Set resume file transfer offset */
|
||||
infof(data, "Instructs server to resume from offset %"
|
||||
CURL_FORMAT_CURL_OFF_T, data->state.resume_from);
|
||||
infof(data, "Instructs server to resume from offset %" FMT_OFF_T,
|
||||
data->state.resume_from);
|
||||
|
||||
result = Curl_pp_sendf(data, &ftpc->pp, "REST %" CURL_FORMAT_CURL_OFF_T,
|
||||
result = Curl_pp_sendf(data, &ftpc->pp, "REST %" FMT_OFF_T,
|
||||
data->state.resume_from);
|
||||
if(!result)
|
||||
ftp_state(data, FTP_RETR_REST);
|
||||
@@ -2479,7 +2486,7 @@ static CURLcode ftp_state_size_resp(struct Curl_easy *data,
|
||||
if(-1 != filesize) {
|
||||
char clbuf[128];
|
||||
int clbuflen = msnprintf(clbuf, sizeof(clbuf),
|
||||
"Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize);
|
||||
"Content-Length: %" FMT_OFF_T "\r\n", filesize);
|
||||
result = client_write_header(data, clbuf, clbuflen);
|
||||
if(result)
|
||||
return result;
|
||||
@@ -2659,12 +2666,10 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data,
|
||||
else if((instate != FTP_LIST) && (data->state.prefer_ascii))
|
||||
size = -1; /* kludge for servers that understate ASCII mode file size */
|
||||
|
||||
infof(data, "Maxdownload = %" CURL_FORMAT_CURL_OFF_T,
|
||||
data->req.maxdownload);
|
||||
infof(data, "Maxdownload = %" FMT_OFF_T, data->req.maxdownload);
|
||||
|
||||
if(instate != FTP_LIST)
|
||||
infof(data, "Getting file with size: %" CURL_FORMAT_CURL_OFF_T,
|
||||
size);
|
||||
infof(data, "Getting file with size: %" FMT_OFF_T, size);
|
||||
|
||||
/* FTP download: */
|
||||
conn->proto.ftpc.state_saved = instate;
|
||||
@@ -3529,8 +3534,8 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status,
|
||||
(data->state.infilesize != data->req.writebytecount) &&
|
||||
!data->set.crlf &&
|
||||
(ftp->transfer == PPTRANSFER_BODY)) {
|
||||
failf(data, "Uploaded unaligned file size (%" CURL_FORMAT_CURL_OFF_T
|
||||
" out of %" CURL_FORMAT_CURL_OFF_T " bytes)",
|
||||
failf(data, "Uploaded unaligned file size (%" FMT_OFF_T
|
||||
" out of %" FMT_OFF_T " bytes)",
|
||||
data->req.writebytecount, data->state.infilesize);
|
||||
result = CURLE_PARTIAL_FILE;
|
||||
}
|
||||
@@ -3538,17 +3543,9 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status,
|
||||
else {
|
||||
if((-1 != data->req.size) &&
|
||||
(data->req.size != data->req.bytecount) &&
|
||||
#ifdef CURL_DO_LINEEND_CONV
|
||||
/* Most FTP servers do not adjust their file SIZE response for CRLFs,
|
||||
* so we will check to see if the discrepancy can be explained by the
|
||||
* number of CRLFs we have changed to LFs.
|
||||
*/
|
||||
((data->req.size + data->state.crlf_conversions) !=
|
||||
data->req.bytecount) &&
|
||||
#endif /* CURL_DO_LINEEND_CONV */
|
||||
(data->req.maxdownload != data->req.bytecount)) {
|
||||
failf(data, "Received only partial file: %" CURL_FORMAT_CURL_OFF_T
|
||||
" bytes", data->req.bytecount);
|
||||
failf(data, "Received only partial file: %" FMT_OFF_T " bytes",
|
||||
data->req.bytecount);
|
||||
result = CURLE_PARTIAL_FILE;
|
||||
}
|
||||
else if(!ftpc->dont_check &&
|
||||
@@ -3684,7 +3681,7 @@ static CURLcode ftp_nb_type(struct Curl_easy *data,
|
||||
static void
|
||||
ftp_pasv_verbose(struct Curl_easy *data,
|
||||
struct Curl_addrinfo *ai,
|
||||
char *newhost, /* ascii version */
|
||||
char *newhost, /* ASCII version */
|
||||
int port)
|
||||
{
|
||||
char buf[256];
|
||||
@@ -4027,7 +4024,7 @@ static CURLcode wc_statemach(struct Curl_easy *data)
|
||||
wildcard->state = CURLWC_CLEAN;
|
||||
continue;
|
||||
}
|
||||
if(wildcard->filelist.size == 0) {
|
||||
if(Curl_llist_count(&wildcard->filelist) == 0) {
|
||||
/* no corresponding file */
|
||||
wildcard->state = CURLWC_CLEAN;
|
||||
return CURLE_REMOTE_FILE_NOT_FOUND;
|
||||
@@ -4038,7 +4035,8 @@ static CURLcode wc_statemach(struct Curl_easy *data)
|
||||
case CURLWC_DOWNLOADING: {
|
||||
/* filelist has at least one file, lets get first one */
|
||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||
struct curl_fileinfo *finfo = wildcard->filelist.head->ptr;
|
||||
struct Curl_llist_node *head = Curl_llist_head(&wildcard->filelist);
|
||||
struct curl_fileinfo *finfo = Curl_node_elem(head);
|
||||
struct FTP *ftp = data->req.p.ftp;
|
||||
|
||||
char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename);
|
||||
@@ -4054,7 +4052,8 @@ static CURLcode wc_statemach(struct Curl_easy *data)
|
||||
long userresponse;
|
||||
Curl_set_in_callback(data, true);
|
||||
userresponse = data->set.chunk_bgn(
|
||||
finfo, data->set.wildcardptr, (int)wildcard->filelist.size);
|
||||
finfo, data->set.wildcardptr,
|
||||
(int)Curl_llist_count(&wildcard->filelist));
|
||||
Curl_set_in_callback(data, false);
|
||||
switch(userresponse) {
|
||||
case CURL_CHUNK_BGN_FUNC_SKIP:
|
||||
@@ -4080,9 +4079,10 @@ static CURLcode wc_statemach(struct Curl_easy *data)
|
||||
return result;
|
||||
|
||||
/* we do not need the Curl_fileinfo of first file anymore */
|
||||
Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL);
|
||||
Curl_node_remove(Curl_llist_head(&wildcard->filelist));
|
||||
|
||||
if(wildcard->filelist.size == 0) { /* remains only one file to down. */
|
||||
if(Curl_llist_count(&wildcard->filelist) == 0) {
|
||||
/* remains only one file to down. */
|
||||
wildcard->state = CURLWC_CLEAN;
|
||||
/* after that will be ftp_do called once again and no transfer
|
||||
will be done because of CURLWC_CLEAN state */
|
||||
@@ -4097,8 +4097,8 @@ static CURLcode wc_statemach(struct Curl_easy *data)
|
||||
data->set.chunk_end(data->set.wildcardptr);
|
||||
Curl_set_in_callback(data, false);
|
||||
}
|
||||
Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL);
|
||||
wildcard->state = (wildcard->filelist.size == 0) ?
|
||||
Curl_node_remove(Curl_llist_head(&wildcard->filelist));
|
||||
wildcard->state = (Curl_llist_count(&wildcard->filelist) == 0) ?
|
||||
CURLWC_CLEAN : CURLWC_DOWNLOADING;
|
||||
continue;
|
||||
}
|
||||
@@ -4144,7 +4144,7 @@ static CURLcode ftp_do(struct Curl_easy *data, bool *done)
|
||||
*done = FALSE; /* default to false */
|
||||
ftpc->wait_data_conn = FALSE; /* default to no such wait */
|
||||
|
||||
#ifdef CURL_DO_LINEEND_CONV
|
||||
#ifdef CURL_PREFER_LF_LINEENDS
|
||||
{
|
||||
/* FTP data may need conversion. */
|
||||
struct Curl_cwriter *ftp_lc_writer;
|
||||
@@ -4160,7 +4160,7 @@ static CURLcode ftp_do(struct Curl_easy *data, bool *done)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
#endif /* CURL_DO_LINEEND_CONV */
|
||||
#endif /* CURL_PREFER_LF_LINEENDS */
|
||||
|
||||
if(data->state.wildcardmatch) {
|
||||
result = wc_statemach(data);
|
||||
|
||||
+30
-18
@@ -53,6 +53,7 @@ CURLcode Curl_initinfo(struct Curl_easy *data)
|
||||
pro->t_connect = 0;
|
||||
pro->t_appconnect = 0;
|
||||
pro->t_pretransfer = 0;
|
||||
pro->t_posttransfer = 0;
|
||||
pro->t_starttransfer = 0;
|
||||
pro->timespent = 0;
|
||||
pro->t_redirect = 0;
|
||||
@@ -76,10 +77,9 @@ CURLcode Curl_initinfo(struct Curl_easy *data)
|
||||
free(info->wouldredirect);
|
||||
info->wouldredirect = NULL;
|
||||
|
||||
info->primary.remote_ip[0] = '\0';
|
||||
info->primary.local_ip[0] = '\0';
|
||||
info->primary.remote_port = 0;
|
||||
info->primary.local_port = 0;
|
||||
memset(&info->primary, 0, sizeof(info->primary));
|
||||
info->primary.remote_port = -1;
|
||||
info->primary.local_port = -1;
|
||||
info->retry_after = 0;
|
||||
|
||||
info->conn_scheme = 0;
|
||||
@@ -252,11 +252,13 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
|
||||
case CURLINFO_SSL_VERIFYRESULT:
|
||||
*param_longp = data->set.ssl.certverifyresult;
|
||||
break;
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
case CURLINFO_PROXY_SSL_VERIFYRESULT:
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
*param_longp = data->set.proxy_ssl.certverifyresult;
|
||||
break;
|
||||
#else
|
||||
*param_longp = 0;
|
||||
#endif
|
||||
break;
|
||||
case CURLINFO_REDIRECT_COUNT:
|
||||
*param_longp = data->state.followlocation;
|
||||
break;
|
||||
@@ -314,6 +316,12 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
|
||||
case CURLINFO_RTSP_CSEQ_RECV:
|
||||
*param_longp = data->state.rtsp_CSeq_recv;
|
||||
break;
|
||||
#else
|
||||
case CURLINFO_RTSP_CLIENT_CSEQ:
|
||||
case CURLINFO_RTSP_SERVER_CSEQ:
|
||||
case CURLINFO_RTSP_CSEQ_RECV:
|
||||
*param_longp = 0;
|
||||
break;
|
||||
#endif
|
||||
case CURLINFO_HTTP_VERSION:
|
||||
switch(data->info.httpversion) {
|
||||
@@ -368,6 +376,7 @@ static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
|
||||
case CURLINFO_CONNECT_TIME_T:
|
||||
case CURLINFO_APPCONNECT_TIME_T:
|
||||
case CURLINFO_PRETRANSFER_TIME_T:
|
||||
case CURLINFO_POSTTRANSFER_TIME_T:
|
||||
case CURLINFO_STARTTRANSFER_TIME_T:
|
||||
case CURLINFO_REDIRECT_TIME_T:
|
||||
case CURLINFO_SPEED_DOWNLOAD_T:
|
||||
@@ -384,24 +393,24 @@ static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
|
||||
*param_offt = (curl_off_t)data->info.filetime;
|
||||
break;
|
||||
case CURLINFO_SIZE_UPLOAD_T:
|
||||
*param_offt = data->progress.uploaded;
|
||||
*param_offt = data->progress.ul.cur_size;
|
||||
break;
|
||||
case CURLINFO_SIZE_DOWNLOAD_T:
|
||||
*param_offt = data->progress.downloaded;
|
||||
*param_offt = data->progress.dl.cur_size;
|
||||
break;
|
||||
case CURLINFO_SPEED_DOWNLOAD_T:
|
||||
*param_offt = data->progress.dlspeed;
|
||||
*param_offt = data->progress.dl.speed;
|
||||
break;
|
||||
case CURLINFO_SPEED_UPLOAD_T:
|
||||
*param_offt = data->progress.ulspeed;
|
||||
*param_offt = data->progress.ul.speed;
|
||||
break;
|
||||
case CURLINFO_CONTENT_LENGTH_DOWNLOAD_T:
|
||||
*param_offt = (data->progress.flags & PGRS_DL_SIZE_KNOWN)?
|
||||
data->progress.size_dl:-1;
|
||||
data->progress.dl.total_size:-1;
|
||||
break;
|
||||
case CURLINFO_CONTENT_LENGTH_UPLOAD_T:
|
||||
*param_offt = (data->progress.flags & PGRS_UL_SIZE_KNOWN)?
|
||||
data->progress.size_ul:-1;
|
||||
data->progress.ul.total_size:-1;
|
||||
break;
|
||||
case CURLINFO_TOTAL_TIME_T:
|
||||
*param_offt = data->progress.timespent;
|
||||
@@ -418,6 +427,9 @@ static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
|
||||
case CURLINFO_PRETRANSFER_TIME_T:
|
||||
*param_offt = data->progress.t_pretransfer;
|
||||
break;
|
||||
case CURLINFO_POSTTRANSFER_TIME_T:
|
||||
*param_offt = data->progress.t_posttransfer;
|
||||
break;
|
||||
case CURLINFO_STARTTRANSFER_TIME_T:
|
||||
*param_offt = data->progress.t_starttransfer;
|
||||
break;
|
||||
@@ -488,24 +500,24 @@ static CURLcode getinfo_double(struct Curl_easy *data, CURLINFO info,
|
||||
*param_doublep = DOUBLE_SECS(data->progress.t_starttransfer);
|
||||
break;
|
||||
case CURLINFO_SIZE_UPLOAD:
|
||||
*param_doublep = (double)data->progress.uploaded;
|
||||
*param_doublep = (double)data->progress.ul.cur_size;
|
||||
break;
|
||||
case CURLINFO_SIZE_DOWNLOAD:
|
||||
*param_doublep = (double)data->progress.downloaded;
|
||||
*param_doublep = (double)data->progress.dl.cur_size;
|
||||
break;
|
||||
case CURLINFO_SPEED_DOWNLOAD:
|
||||
*param_doublep = (double)data->progress.dlspeed;
|
||||
*param_doublep = (double)data->progress.dl.speed;
|
||||
break;
|
||||
case CURLINFO_SPEED_UPLOAD:
|
||||
*param_doublep = (double)data->progress.ulspeed;
|
||||
*param_doublep = (double)data->progress.ul.speed;
|
||||
break;
|
||||
case CURLINFO_CONTENT_LENGTH_DOWNLOAD:
|
||||
*param_doublep = (data->progress.flags & PGRS_DL_SIZE_KNOWN)?
|
||||
(double)data->progress.size_dl:-1;
|
||||
(double)data->progress.dl.total_size:-1;
|
||||
break;
|
||||
case CURLINFO_CONTENT_LENGTH_UPLOAD:
|
||||
*param_doublep = (data->progress.flags & PGRS_UL_SIZE_KNOWN)?
|
||||
(double)data->progress.size_ul:-1;
|
||||
(double)data->progress.ul.total_size:-1;
|
||||
break;
|
||||
case CURLINFO_REDIRECT_TIME:
|
||||
*param_doublep = DOUBLE_SECS(data->progress.t_redirect);
|
||||
|
||||
+2
-2
@@ -187,7 +187,7 @@ static CURLcode gopher_do(struct Curl_easy *data, bool *done)
|
||||
if(strlen(sel) < 1)
|
||||
break;
|
||||
|
||||
result = Curl_xfer_send(data, sel, k, &amount);
|
||||
result = Curl_xfer_send(data, sel, k, FALSE, &amount);
|
||||
if(!result) { /* Which may not have written it all! */
|
||||
result = Curl_client_write(data, CLIENTWRITE_HEADER, sel, amount);
|
||||
if(result)
|
||||
@@ -229,7 +229,7 @@ static CURLcode gopher_do(struct Curl_easy *data, bool *done)
|
||||
free(sel_org);
|
||||
|
||||
if(!result)
|
||||
result = Curl_xfer_send(data, "\r\n", 2, &amount);
|
||||
result = Curl_xfer_send(data, "\r\n", 2, FALSE, &amount);
|
||||
if(result) {
|
||||
failf(data, "Failed sending Gopher request");
|
||||
return result;
|
||||
|
||||
+48
-30
@@ -33,6 +33,10 @@
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
|
||||
/* random patterns for API verification */
|
||||
#define HASHINIT 0x7017e781
|
||||
#define ITERINIT 0x5FEDCBA9
|
||||
|
||||
static void
|
||||
hash_element_dtor(void *user, void *element)
|
||||
{
|
||||
@@ -77,6 +81,9 @@ Curl_hash_init(struct Curl_hash *h,
|
||||
h->dtor = dtor;
|
||||
h->size = 0;
|
||||
h->slots = slots;
|
||||
#ifdef DEBUGBUILD
|
||||
h->init = HASHINIT;
|
||||
#endif
|
||||
}
|
||||
|
||||
static struct Curl_hash_element *
|
||||
@@ -102,11 +109,12 @@ void *Curl_hash_add2(struct Curl_hash *h, void *key, size_t key_len, void *p,
|
||||
Curl_hash_elem_dtor dtor)
|
||||
{
|
||||
struct Curl_hash_element *he;
|
||||
struct Curl_llist_element *le;
|
||||
struct Curl_llist_node *le;
|
||||
struct Curl_llist *l;
|
||||
|
||||
DEBUGASSERT(h);
|
||||
DEBUGASSERT(h->slots);
|
||||
DEBUGASSERT(h->init == HASHINIT);
|
||||
if(!h->table) {
|
||||
size_t i;
|
||||
h->table = malloc(h->slots * sizeof(struct Curl_llist));
|
||||
@@ -118,10 +126,10 @@ void *Curl_hash_add2(struct Curl_hash *h, void *key, size_t key_len, void *p,
|
||||
|
||||
l = FETCH_LIST(h, key, key_len);
|
||||
|
||||
for(le = l->head; le; le = le->next) {
|
||||
he = (struct Curl_hash_element *) le->ptr;
|
||||
for(le = Curl_llist_head(l); le; le = Curl_node_next(le)) {
|
||||
he = (struct Curl_hash_element *) Curl_node_elem(le);
|
||||
if(h->comp_func(he->key, he->key_len, key, key_len)) {
|
||||
Curl_llist_remove(l, le, (void *)h);
|
||||
Curl_node_uremove(le, (void *)h);
|
||||
--h->size;
|
||||
break;
|
||||
}
|
||||
@@ -158,18 +166,17 @@ Curl_hash_add(struct Curl_hash *h, void *key, size_t key_len, void *p)
|
||||
*/
|
||||
int Curl_hash_delete(struct Curl_hash *h, void *key, size_t key_len)
|
||||
{
|
||||
struct Curl_llist_element *le;
|
||||
struct Curl_llist *l;
|
||||
|
||||
DEBUGASSERT(h);
|
||||
DEBUGASSERT(h->slots);
|
||||
DEBUGASSERT(h->init == HASHINIT);
|
||||
if(h->table) {
|
||||
l = FETCH_LIST(h, key, key_len);
|
||||
struct Curl_llist_node *le;
|
||||
struct Curl_llist *l = FETCH_LIST(h, key, key_len);
|
||||
|
||||
for(le = l->head; le; le = le->next) {
|
||||
struct Curl_hash_element *he = le->ptr;
|
||||
for(le = Curl_llist_head(l); le; le = Curl_node_next(le)) {
|
||||
struct Curl_hash_element *he = Curl_node_elem(le);
|
||||
if(h->comp_func(he->key, he->key_len, key, key_len)) {
|
||||
Curl_llist_remove(l, le, (void *) h);
|
||||
Curl_node_uremove(le, (void *) h);
|
||||
--h->size;
|
||||
return 0;
|
||||
}
|
||||
@@ -185,15 +192,15 @@ int Curl_hash_delete(struct Curl_hash *h, void *key, size_t key_len)
|
||||
void *
|
||||
Curl_hash_pick(struct Curl_hash *h, void *key, size_t key_len)
|
||||
{
|
||||
struct Curl_llist_element *le;
|
||||
struct Curl_llist *l;
|
||||
|
||||
DEBUGASSERT(h);
|
||||
DEBUGASSERT(h->init == HASHINIT);
|
||||
if(h->table) {
|
||||
struct Curl_llist_node *le;
|
||||
struct Curl_llist *l;
|
||||
DEBUGASSERT(h->slots);
|
||||
l = FETCH_LIST(h, key, key_len);
|
||||
for(le = l->head; le; le = le->next) {
|
||||
struct Curl_hash_element *he = le->ptr;
|
||||
for(le = Curl_llist_head(l); le; le = Curl_node_next(le)) {
|
||||
struct Curl_hash_element *he = Curl_node_elem(le);
|
||||
if(h->comp_func(he->key, he->key_len, key, key_len)) {
|
||||
return he->ptr;
|
||||
}
|
||||
@@ -213,6 +220,7 @@ Curl_hash_pick(struct Curl_hash *h, void *key, size_t key_len)
|
||||
void
|
||||
Curl_hash_destroy(struct Curl_hash *h)
|
||||
{
|
||||
DEBUGASSERT(h->init == HASHINIT);
|
||||
if(h->table) {
|
||||
size_t i;
|
||||
for(i = 0; i < h->slots; ++i) {
|
||||
@@ -234,28 +242,33 @@ Curl_hash_clean(struct Curl_hash *h)
|
||||
Curl_hash_clean_with_criterium(h, NULL, NULL);
|
||||
}
|
||||
|
||||
size_t Curl_hash_count(struct Curl_hash *h)
|
||||
{
|
||||
DEBUGASSERT(h->init == HASHINIT);
|
||||
return h->size;
|
||||
}
|
||||
|
||||
/* Cleans all entries that pass the comp function criteria. */
|
||||
void
|
||||
Curl_hash_clean_with_criterium(struct Curl_hash *h, void *user,
|
||||
int (*comp)(void *, void *))
|
||||
{
|
||||
struct Curl_llist_element *le;
|
||||
struct Curl_llist_element *lnext;
|
||||
struct Curl_llist *list;
|
||||
size_t i;
|
||||
|
||||
if(!h || !h->table)
|
||||
return;
|
||||
|
||||
DEBUGASSERT(h->init == HASHINIT);
|
||||
for(i = 0; i < h->slots; ++i) {
|
||||
list = &h->table[i];
|
||||
le = list->head; /* get first list entry */
|
||||
struct Curl_llist *list = &h->table[i];
|
||||
struct Curl_llist_node *le =
|
||||
Curl_llist_head(list); /* get first list entry */
|
||||
while(le) {
|
||||
struct Curl_hash_element *he = le->ptr;
|
||||
lnext = le->next;
|
||||
struct Curl_hash_element *he = Curl_node_elem(le);
|
||||
struct Curl_llist_node *lnext = Curl_node_next(le);
|
||||
/* ask the callback function if we shall remove this entry or not */
|
||||
if(!comp || comp(user, he->ptr)) {
|
||||
Curl_llist_remove(list, le, (void *) h);
|
||||
Curl_node_uremove(le, (void *) h);
|
||||
--h->size; /* one less entry in the hash now */
|
||||
}
|
||||
le = lnext;
|
||||
@@ -290,29 +303,34 @@ size_t Curl_str_key_compare(void *k1, size_t key1_len,
|
||||
void Curl_hash_start_iterate(struct Curl_hash *hash,
|
||||
struct Curl_hash_iterator *iter)
|
||||
{
|
||||
DEBUGASSERT(hash->init == HASHINIT);
|
||||
iter->hash = hash;
|
||||
iter->slot_index = 0;
|
||||
iter->current_element = NULL;
|
||||
#ifdef DEBUGBUILD
|
||||
iter->init = ITERINIT;
|
||||
#endif
|
||||
}
|
||||
|
||||
struct Curl_hash_element *
|
||||
Curl_hash_next_element(struct Curl_hash_iterator *iter)
|
||||
{
|
||||
struct Curl_hash *h = iter->hash;
|
||||
|
||||
struct Curl_hash *h;
|
||||
DEBUGASSERT(iter->init == ITERINIT);
|
||||
h = iter->hash;
|
||||
if(!h->table)
|
||||
return NULL; /* empty hash, nothing to return */
|
||||
|
||||
/* Get the next element in the current list, if any */
|
||||
if(iter->current_element)
|
||||
iter->current_element = iter->current_element->next;
|
||||
iter->current_element = Curl_node_next(iter->current_element);
|
||||
|
||||
/* If we have reached the end of the list, find the next one */
|
||||
if(!iter->current_element) {
|
||||
size_t i;
|
||||
for(i = iter->slot_index; i < h->slots; i++) {
|
||||
if(h->table[i].head) {
|
||||
iter->current_element = h->table[i].head;
|
||||
if(Curl_llist_head(&h->table[i])) {
|
||||
iter->current_element = Curl_llist_head(&h->table[i]);
|
||||
iter->slot_index = i + 1;
|
||||
break;
|
||||
}
|
||||
@@ -320,7 +338,7 @@ Curl_hash_next_element(struct Curl_hash_iterator *iter)
|
||||
}
|
||||
|
||||
if(iter->current_element) {
|
||||
struct Curl_hash_element *he = iter->current_element->ptr;
|
||||
struct Curl_hash_element *he = Curl_node_elem(iter->current_element);
|
||||
return he;
|
||||
}
|
||||
return NULL;
|
||||
|
||||
+13
-3
@@ -56,22 +56,31 @@ struct Curl_hash {
|
||||
Curl_hash_dtor dtor;
|
||||
size_t slots;
|
||||
size_t size;
|
||||
#ifdef DEBUGBUILD
|
||||
int init;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef void (*Curl_hash_elem_dtor)(void *key, size_t key_len, void *p);
|
||||
|
||||
struct Curl_hash_element {
|
||||
struct Curl_llist_element list;
|
||||
struct Curl_llist_node list;
|
||||
void *ptr;
|
||||
Curl_hash_elem_dtor dtor;
|
||||
size_t key_len;
|
||||
#ifdef DEBUGBUILD
|
||||
int init;
|
||||
#endif
|
||||
char key[1]; /* allocated memory following the struct */
|
||||
};
|
||||
|
||||
struct Curl_hash_iterator {
|
||||
struct Curl_hash *hash;
|
||||
size_t slot_index;
|
||||
struct Curl_llist_element *current_element;
|
||||
struct Curl_llist_node *current_element;
|
||||
#ifdef DEBUGBUILD
|
||||
int init;
|
||||
#endif
|
||||
};
|
||||
|
||||
void Curl_hash_init(struct Curl_hash *h,
|
||||
@@ -85,8 +94,9 @@ void *Curl_hash_add2(struct Curl_hash *h, void *key, size_t key_len, void *p,
|
||||
Curl_hash_elem_dtor dtor);
|
||||
int Curl_hash_delete(struct Curl_hash *h, void *key, size_t key_len);
|
||||
void *Curl_hash_pick(struct Curl_hash *, void *key, size_t key_len);
|
||||
#define Curl_hash_count(h) ((h)->size)
|
||||
|
||||
void Curl_hash_destroy(struct Curl_hash *h);
|
||||
size_t Curl_hash_count(struct Curl_hash *h);
|
||||
void Curl_hash_clean(struct Curl_hash *h);
|
||||
void Curl_hash_clean_with_criterium(struct Curl_hash *h, void *user,
|
||||
int (*comp)(void *, void *));
|
||||
|
||||
+22
-22
@@ -42,7 +42,7 @@
|
||||
static void copy_header_external(struct Curl_header_store *hs,
|
||||
size_t index,
|
||||
size_t amount,
|
||||
struct Curl_llist_element *e,
|
||||
struct Curl_llist_node *e,
|
||||
struct curl_header *hout)
|
||||
{
|
||||
struct curl_header *h = hout;
|
||||
@@ -66,8 +66,8 @@ CURLHcode curl_easy_header(CURL *easy,
|
||||
int request,
|
||||
struct curl_header **hout)
|
||||
{
|
||||
struct Curl_llist_element *e;
|
||||
struct Curl_llist_element *e_pick = NULL;
|
||||
struct Curl_llist_node *e;
|
||||
struct Curl_llist_node *e_pick = NULL;
|
||||
struct Curl_easy *data = easy;
|
||||
size_t match = 0;
|
||||
size_t amount = 0;
|
||||
@@ -85,8 +85,8 @@ CURLHcode curl_easy_header(CURL *easy,
|
||||
request = data->state.requests;
|
||||
|
||||
/* we need a first round to count amount of this header */
|
||||
for(e = data->state.httphdrs.head; e; e = e->next) {
|
||||
hs = e->ptr;
|
||||
for(e = Curl_llist_head(&data->state.httphdrs); e; e = Curl_node_next(e)) {
|
||||
hs = Curl_node_elem(e);
|
||||
if(strcasecompare(hs->name, name) &&
|
||||
(hs->type & type) &&
|
||||
(hs->request == request)) {
|
||||
@@ -104,8 +104,8 @@ CURLHcode curl_easy_header(CURL *easy,
|
||||
/* if the last or only occurrence is what's asked for, then we know it */
|
||||
hs = pick;
|
||||
else {
|
||||
for(e = data->state.httphdrs.head; e; e = e->next) {
|
||||
hs = e->ptr;
|
||||
for(e = Curl_llist_head(&data->state.httphdrs); e; e = Curl_node_next(e)) {
|
||||
hs = Curl_node_elem(e);
|
||||
if(strcasecompare(hs->name, name) &&
|
||||
(hs->type & type) &&
|
||||
(hs->request == request) &&
|
||||
@@ -131,8 +131,8 @@ struct curl_header *curl_easy_nextheader(CURL *easy,
|
||||
struct curl_header *prev)
|
||||
{
|
||||
struct Curl_easy *data = easy;
|
||||
struct Curl_llist_element *pick;
|
||||
struct Curl_llist_element *e;
|
||||
struct Curl_llist_node *pick;
|
||||
struct Curl_llist_node *e;
|
||||
struct Curl_header_store *hs;
|
||||
size_t amount = 0;
|
||||
size_t index = 0;
|
||||
@@ -147,18 +147,18 @@ struct curl_header *curl_easy_nextheader(CURL *easy,
|
||||
if(!pick)
|
||||
/* something is wrong */
|
||||
return NULL;
|
||||
pick = pick->next;
|
||||
pick = Curl_node_next(pick);
|
||||
}
|
||||
else
|
||||
pick = data->state.httphdrs.head;
|
||||
pick = Curl_llist_head(&data->state.httphdrs);
|
||||
|
||||
if(pick) {
|
||||
/* make sure it is the next header of the desired type */
|
||||
do {
|
||||
hs = pick->ptr;
|
||||
hs = Curl_node_elem(pick);
|
||||
if((hs->type & type) && (hs->request == request))
|
||||
break;
|
||||
pick = pick->next;
|
||||
pick = Curl_node_next(pick);
|
||||
} while(pick);
|
||||
}
|
||||
|
||||
@@ -166,12 +166,12 @@ struct curl_header *curl_easy_nextheader(CURL *easy,
|
||||
/* no more headers available */
|
||||
return NULL;
|
||||
|
||||
hs = pick->ptr;
|
||||
hs = Curl_node_elem(pick);
|
||||
|
||||
/* count number of occurrences of this name within the mask and figure out
|
||||
the index for the currently selected entry */
|
||||
for(e = data->state.httphdrs.head; e; e = e->next) {
|
||||
struct Curl_header_store *check = e->ptr;
|
||||
for(e = Curl_llist_head(&data->state.httphdrs); e; e = Curl_node_next(e)) {
|
||||
struct Curl_header_store *check = Curl_node_elem(e);
|
||||
if(strcasecompare(hs->name, check->name) &&
|
||||
(check->request == request) &&
|
||||
(check->type & type))
|
||||
@@ -247,7 +247,7 @@ static CURLcode unfold_value(struct Curl_easy *data, const char *value,
|
||||
/* since this header block might move in the realloc below, it needs to
|
||||
first be unlinked from the list and then re-added again after the
|
||||
realloc */
|
||||
Curl_llist_remove(&data->state.httphdrs, &hs->node, NULL);
|
||||
Curl_node_remove(&hs->node);
|
||||
|
||||
/* new size = struct + new value length + old name+value length */
|
||||
newhs = Curl_saferealloc(hs, sizeof(*hs) + vlen + oalloc + 1);
|
||||
@@ -405,12 +405,12 @@ CURLcode Curl_headers_init(struct Curl_easy *data)
|
||||
*/
|
||||
CURLcode Curl_headers_cleanup(struct Curl_easy *data)
|
||||
{
|
||||
struct Curl_llist_element *e;
|
||||
struct Curl_llist_element *n;
|
||||
struct Curl_llist_node *e;
|
||||
struct Curl_llist_node *n;
|
||||
|
||||
for(e = data->state.httphdrs.head; e; e = n) {
|
||||
struct Curl_header_store *hs = e->ptr;
|
||||
n = e->next;
|
||||
for(e = Curl_llist_head(&data->state.httphdrs); e; e = n) {
|
||||
struct Curl_header_store *hs = Curl_node_elem(e);
|
||||
n = Curl_node_next(e);
|
||||
free(hs);
|
||||
}
|
||||
headers_reset(data);
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@
|
||||
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_HEADERS_API)
|
||||
|
||||
struct Curl_header_store {
|
||||
struct Curl_llist_element node;
|
||||
struct Curl_llist_node node;
|
||||
char *name; /* points into 'buffer' */
|
||||
char *value; /* points into 'buffer */
|
||||
int request; /* 0 is the first request, then 1.. 2.. */
|
||||
|
||||
+1
-1
@@ -79,7 +79,7 @@ CURLcode Curl_addrinfo_callback(struct Curl_easy *data,
|
||||
|
||||
dns = Curl_cache_addr(data, ai,
|
||||
data->state.async.hostname, 0,
|
||||
data->state.async.port);
|
||||
data->state.async.port, FALSE);
|
||||
if(data->share)
|
||||
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
|
||||
|
||||
|
||||
+49
-44
@@ -115,7 +115,7 @@
|
||||
* CURLRES_* defines based on the config*.h and curl_setup.h defines.
|
||||
*/
|
||||
|
||||
static void freednsentry(void *freethis);
|
||||
static void hostcache_unlink_entry(void *entry);
|
||||
|
||||
#ifndef CURL_DISABLE_VERBOSE_STRINGS
|
||||
static void show_resolve_info(struct Curl_easy *data,
|
||||
@@ -178,7 +178,7 @@ create_hostcache_id(const char *name,
|
||||
struct hostcache_prune_data {
|
||||
time_t now;
|
||||
time_t oldest; /* oldest time in cache not pruned. */
|
||||
int cache_timeout;
|
||||
int max_age_sec;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -189,16 +189,16 @@ struct hostcache_prune_data {
|
||||
* cache.
|
||||
*/
|
||||
static int
|
||||
hostcache_timestamp_remove(void *datap, void *hc)
|
||||
hostcache_entry_is_stale(void *datap, void *hc)
|
||||
{
|
||||
struct hostcache_prune_data *prune =
|
||||
(struct hostcache_prune_data *) datap;
|
||||
struct Curl_dns_entry *c = (struct Curl_dns_entry *) hc;
|
||||
struct Curl_dns_entry *dns = (struct Curl_dns_entry *) hc;
|
||||
|
||||
if(c->timestamp) {
|
||||
if(dns->timestamp) {
|
||||
/* age in seconds */
|
||||
time_t age = prune->now - c->timestamp;
|
||||
if(age >= prune->cache_timeout)
|
||||
time_t age = prune->now - dns->timestamp;
|
||||
if(age >= prune->max_age_sec)
|
||||
return TRUE;
|
||||
if(age > prune->oldest)
|
||||
prune->oldest = age;
|
||||
@@ -216,13 +216,13 @@ hostcache_prune(struct Curl_hash *hostcache, int cache_timeout,
|
||||
{
|
||||
struct hostcache_prune_data user;
|
||||
|
||||
user.cache_timeout = cache_timeout;
|
||||
user.max_age_sec = cache_timeout;
|
||||
user.now = now;
|
||||
user.oldest = 0;
|
||||
|
||||
Curl_hash_clean_with_criterium(hostcache,
|
||||
(void *) &user,
|
||||
hostcache_timestamp_remove);
|
||||
hostcache_entry_is_stale);
|
||||
|
||||
return user.oldest;
|
||||
}
|
||||
@@ -257,7 +257,8 @@ void Curl_hostcache_prune(struct Curl_easy *data)
|
||||
|
||||
/* if the cache size is still too big, use the oldest age as new
|
||||
prune limit */
|
||||
} while(timeout && (data->dns.hostcache->size > MAX_DNS_CACHE_SIZE));
|
||||
} while(timeout &&
|
||||
(Curl_hash_count(data->dns.hostcache) > MAX_DNS_CACHE_SIZE));
|
||||
|
||||
if(data->share)
|
||||
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
|
||||
@@ -299,10 +300,10 @@ static struct Curl_dns_entry *fetch_addr(struct Curl_easy *data,
|
||||
struct hostcache_prune_data user;
|
||||
|
||||
user.now = time(NULL);
|
||||
user.cache_timeout = data->set.dns_cache_timeout;
|
||||
user.max_age_sec = data->set.dns_cache_timeout;
|
||||
user.oldest = 0;
|
||||
|
||||
if(hostcache_timestamp_remove(&user, dns)) {
|
||||
if(hostcache_entry_is_stale(&user, dns)) {
|
||||
infof(data, "Hostname in DNS cache was stale, zapped");
|
||||
dns = NULL; /* the memory deallocation is being handled by the hash */
|
||||
Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1);
|
||||
@@ -348,7 +349,7 @@ static struct Curl_dns_entry *fetch_addr(struct Curl_easy *data,
|
||||
*
|
||||
* Returns the Curl_dns_entry entry pointer or NULL if not in the cache.
|
||||
*
|
||||
* The returned data *MUST* be "unlocked" with Curl_resolv_unlock() after
|
||||
* The returned data *MUST* be "released" with Curl_resolv_unlink() after
|
||||
* use, or we will leak memory!
|
||||
*/
|
||||
struct Curl_dns_entry *
|
||||
@@ -364,7 +365,7 @@ Curl_fetch_addr(struct Curl_easy *data,
|
||||
dns = fetch_addr(data, hostname, port);
|
||||
|
||||
if(dns)
|
||||
dns->inuse++; /* we use it! */
|
||||
dns->refcount++; /* we use it! */
|
||||
|
||||
if(data->share)
|
||||
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
|
||||
@@ -468,7 +469,8 @@ Curl_cache_addr(struct Curl_easy *data,
|
||||
struct Curl_addrinfo *addr,
|
||||
const char *hostname,
|
||||
size_t hostlen, /* length or zero */
|
||||
int port)
|
||||
int port,
|
||||
bool permanent)
|
||||
{
|
||||
char entry_id[MAX_HOSTCACHE_LEN];
|
||||
size_t entry_len;
|
||||
@@ -496,11 +498,15 @@ Curl_cache_addr(struct Curl_easy *data,
|
||||
entry_len = create_hostcache_id(hostname, hostlen, port,
|
||||
entry_id, sizeof(entry_id));
|
||||
|
||||
dns->inuse = 1; /* the cache has the first reference */
|
||||
dns->refcount = 1; /* the cache has the first reference */
|
||||
dns->addr = addr; /* this is the address(es) */
|
||||
time(&dns->timestamp);
|
||||
if(dns->timestamp == 0)
|
||||
dns->timestamp = 1; /* zero indicates permanent CURLOPT_RESOLVE entry */
|
||||
if(permanent)
|
||||
dns->timestamp = 0; /* an entry that never goes stale */
|
||||
else {
|
||||
dns->timestamp = time(NULL);
|
||||
if(dns->timestamp == 0)
|
||||
dns->timestamp = 1;
|
||||
}
|
||||
dns->hostport = port;
|
||||
if(hostlen)
|
||||
memcpy(dns->hostname, hostname, hostlen);
|
||||
@@ -514,7 +520,7 @@ Curl_cache_addr(struct Curl_easy *data,
|
||||
}
|
||||
|
||||
dns = dns2;
|
||||
dns->inuse++; /* mark entry as in-use */
|
||||
dns->refcount++; /* mark entry as in-use */
|
||||
return dns;
|
||||
}
|
||||
|
||||
@@ -666,8 +672,8 @@ static bool tailmatch(const char *full, const char *part)
|
||||
* resolves. See the return codes.
|
||||
*
|
||||
* The cache entry we return will get its 'inuse' counter increased when this
|
||||
* function is used. You MUST call Curl_resolv_unlock() later (when you are
|
||||
* done using this struct) to decrease the counter again.
|
||||
* function is used. You MUST call Curl_resolv_unlink() later (when you are
|
||||
* done using this struct) to decrease the reference counter again.
|
||||
*
|
||||
* Return codes:
|
||||
*
|
||||
@@ -708,7 +714,7 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
|
||||
|
||||
if(dns) {
|
||||
infof(data, "Hostname %s was found in DNS cache", hostname);
|
||||
dns->inuse++; /* we use it! */
|
||||
dns->refcount++; /* we use it! */
|
||||
rc = CURLRESOLV_RESOLVED;
|
||||
}
|
||||
|
||||
@@ -828,7 +834,7 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
|
||||
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
|
||||
|
||||
/* we got a response, store it in the cache */
|
||||
dns = Curl_cache_addr(data, addr, hostname, 0, port);
|
||||
dns = Curl_cache_addr(data, addr, hostname, 0, port, FALSE);
|
||||
|
||||
if(data->share)
|
||||
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
|
||||
@@ -868,8 +874,8 @@ void alarmfunc(int sig)
|
||||
* resolves. See the return codes.
|
||||
*
|
||||
* The cache entry we return will get its 'inuse' counter increased when this
|
||||
* function is used. You MUST call Curl_resolv_unlock() later (when you are
|
||||
* done using this struct) to decrease the counter again.
|
||||
* function is used. You MUST call Curl_resolv_unlink() later (when you are
|
||||
* done using this struct) to decrease the reference counter again.
|
||||
*
|
||||
* If built with a synchronous resolver and use of signals is not
|
||||
* disabled by the application, then a nonzero timeout will cause a
|
||||
@@ -955,7 +961,7 @@ enum resolve_t Curl_resolv_timeout(struct Curl_easy *data,
|
||||
keep_copysig = TRUE; /* yes, we have a copy */
|
||||
sigact.sa_handler = alarmfunc;
|
||||
#ifdef SA_RESTART
|
||||
/* HPUX does not have SA_RESTART but defaults to that behavior! */
|
||||
/* HP-UX does not have SA_RESTART but defaults to that behavior! */
|
||||
sigact.sa_flags &= ~SA_RESTART;
|
||||
#endif
|
||||
/* now set the new struct */
|
||||
@@ -1037,18 +1043,20 @@ clean_up:
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_resolv_unlock() unlocks the given cached DNS entry. When this has been
|
||||
* made, the struct may be destroyed due to pruning. It is important that only
|
||||
* one unlock is made for each Curl_resolv() call.
|
||||
* Curl_resolv_unlink() releases a reference to the given cached DNS entry.
|
||||
* When the reference count reaches 0, the entry is destroyed. It is important
|
||||
* that only one unlink is made for each Curl_resolv() call.
|
||||
*
|
||||
* May be called with 'data' == NULL for global cache.
|
||||
*/
|
||||
void Curl_resolv_unlock(struct Curl_easy *data, struct Curl_dns_entry *dns)
|
||||
void Curl_resolv_unlink(struct Curl_easy *data, struct Curl_dns_entry **pdns)
|
||||
{
|
||||
struct Curl_dns_entry *dns = *pdns;
|
||||
*pdns = NULL;
|
||||
if(data && data->share)
|
||||
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
|
||||
|
||||
freednsentry(dns);
|
||||
hostcache_unlink_entry(dns);
|
||||
|
||||
if(data && data->share)
|
||||
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
|
||||
@@ -1057,13 +1065,13 @@ void Curl_resolv_unlock(struct Curl_easy *data, struct Curl_dns_entry *dns)
|
||||
/*
|
||||
* File-internal: release cache dns entry reference, free if inuse drops to 0
|
||||
*/
|
||||
static void freednsentry(void *freethis)
|
||||
static void hostcache_unlink_entry(void *entry)
|
||||
{
|
||||
struct Curl_dns_entry *dns = (struct Curl_dns_entry *) freethis;
|
||||
DEBUGASSERT(dns && (dns->inuse>0));
|
||||
struct Curl_dns_entry *dns = (struct Curl_dns_entry *) entry;
|
||||
DEBUGASSERT(dns && (dns->refcount>0));
|
||||
|
||||
dns->inuse--;
|
||||
if(dns->inuse == 0) {
|
||||
dns->refcount--;
|
||||
if(dns->refcount == 0) {
|
||||
Curl_freeaddrinfo(dns->addr);
|
||||
#ifdef USE_HTTPSRR
|
||||
if(dns->hinfo) {
|
||||
@@ -1092,7 +1100,7 @@ static void freednsentry(void *freethis)
|
||||
void Curl_init_dnscache(struct Curl_hash *hash, size_t size)
|
||||
{
|
||||
Curl_hash_init(hash, size, Curl_hash_str, Curl_str_key_compare,
|
||||
freednsentry);
|
||||
hostcache_unlink_entry);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1285,13 +1293,11 @@ err:
|
||||
}
|
||||
|
||||
/* put this new host in the cache */
|
||||
dns = Curl_cache_addr(data, head, host_begin, hlen, port);
|
||||
dns = Curl_cache_addr(data, head, host_begin, hlen, port, permanent);
|
||||
if(dns) {
|
||||
if(permanent)
|
||||
dns->timestamp = 0; /* mark as permanent */
|
||||
/* release the returned reference; the cache itself will keep the
|
||||
* entry alive: */
|
||||
dns->inuse--;
|
||||
dns->refcount--;
|
||||
}
|
||||
|
||||
if(data->share)
|
||||
@@ -1443,8 +1449,7 @@ CURLcode Curl_once_resolved(struct Curl_easy *data, bool *protocol_done)
|
||||
|
||||
if(result) {
|
||||
Curl_detach_connection(data);
|
||||
Curl_conncache_remove_conn(data, conn, TRUE);
|
||||
Curl_disconnect(data, conn, TRUE);
|
||||
Curl_cpool_disconnect(data, conn, TRUE);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
+11
-10
@@ -99,11 +99,11 @@ struct Curl_dns_entry {
|
||||
#endif
|
||||
/* timestamp == 0 -- permanent CURLOPT_RESOLVE entry (does not time out) */
|
||||
time_t timestamp;
|
||||
/* use-counter, use Curl_resolv_unlock to release reference */
|
||||
long inuse;
|
||||
/* reference counter, entry is freed on reaching 0 */
|
||||
size_t refcount;
|
||||
/* hostname port number that resolved to addr. */
|
||||
int hostport;
|
||||
/* hostname that resolved to addr. may be NULL (unix domain sockets). */
|
||||
/* hostname that resolved to addr. may be NULL (Unix domain sockets). */
|
||||
char hostname[1];
|
||||
};
|
||||
|
||||
@@ -113,7 +113,7 @@ bool Curl_host_is_ipnum(const char *hostname);
|
||||
* Curl_resolv() returns an entry with the info for the specified host
|
||||
* and port.
|
||||
*
|
||||
* The returned data *MUST* be "unlocked" with Curl_resolv_unlock() after
|
||||
* The returned data *MUST* be "released" with Curl_resolv_unlink() after
|
||||
* use, or we will leak memory!
|
||||
*/
|
||||
/* return codes */
|
||||
@@ -161,9 +161,9 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
|
||||
int *waitp);
|
||||
|
||||
|
||||
/* unlock a previously resolved dns entry */
|
||||
void Curl_resolv_unlock(struct Curl_easy *data,
|
||||
struct Curl_dns_entry *dns);
|
||||
/* unlink a dns entry, potentially shared with a cache */
|
||||
void Curl_resolv_unlink(struct Curl_easy *data,
|
||||
struct Curl_dns_entry **pdns);
|
||||
|
||||
/* init a new dns cache */
|
||||
void Curl_init_dnscache(struct Curl_hash *hash, size_t hashsize);
|
||||
@@ -199,7 +199,7 @@ void Curl_printable_address(const struct Curl_addrinfo *ip,
|
||||
*
|
||||
* Returns the Curl_dns_entry entry pointer or NULL if not in the cache.
|
||||
*
|
||||
* The returned data *MUST* be "unlocked" with Curl_resolv_unlock() after
|
||||
* The returned data *MUST* be "released" with Curl_resolv_unlink() after
|
||||
* use, or we will leak memory!
|
||||
*/
|
||||
struct Curl_dns_entry *
|
||||
@@ -209,12 +209,13 @@ Curl_fetch_addr(struct Curl_easy *data,
|
||||
|
||||
/*
|
||||
* Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache.
|
||||
*
|
||||
* @param permanent iff TRUE, entry will never become stale
|
||||
* Returns the Curl_dns_entry entry pointer or NULL if the storage failed.
|
||||
*/
|
||||
struct Curl_dns_entry *
|
||||
Curl_cache_addr(struct Curl_easy *data, struct Curl_addrinfo *addr,
|
||||
const char *hostname, size_t hostlen, int port);
|
||||
const char *hostname, size_t hostlen, int port,
|
||||
bool permanent);
|
||||
|
||||
#ifndef INADDR_NONE
|
||||
#define CURL_INADDR_NONE (in_addr_t) ~0
|
||||
|
||||
+2
-2
@@ -82,7 +82,7 @@ bool Curl_ipvalid(struct Curl_easy *data, struct connectdata *conn)
|
||||
* detect which one this platform supports in the configure script and set up
|
||||
* the HAVE_GETHOSTBYNAME_R_3, HAVE_GETHOSTBYNAME_R_5 or
|
||||
* HAVE_GETHOSTBYNAME_R_6 defines accordingly. Note that HAVE_GETADDRBYNAME
|
||||
* has the corresponding rules. This is primarily on *nix. Note that some unix
|
||||
* has the corresponding rules. This is primarily on *nix. Note that some Unix
|
||||
* flavours have thread-safe versions of the plain gethostbyname() etc.
|
||||
*
|
||||
*/
|
||||
@@ -221,7 +221,7 @@ struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
|
||||
|
||||
if(!h) /* failure */
|
||||
#elif defined(HAVE_GETHOSTBYNAME_R_3)
|
||||
/* AIX, Digital Unix/Tru64, HPUX 10, more? */
|
||||
/* AIX, Digital UNIX/Tru64, HP-UX 10, more? */
|
||||
|
||||
/* For AIX 4.3 or later, we do not use gethostbyname_r() at all, because of
|
||||
* the plain fact that it does not return unique full buffers on each
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user