mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-06 05:40:54 -06: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})
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
)
|
||||
80
CMake/FindCares.cmake
Normal file
80
CMake/FindCares.cmake
Normal file
@@ -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)
|
||||
@@ -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)
|
||||
78
CMake/FindLibgsasl.cmake
Normal file
78
CMake/FindLibgsasl.cmake
Normal file
@@ -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()
|
||||
78
CMake/FindLibidn2.cmake
Normal file
78
CMake/FindLibidn2.cmake
Normal file
@@ -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()
|
||||
80
CMake/FindLibpsl.cmake
Normal file
80
CMake/FindLibpsl.cmake
Normal file
@@ -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)
|
||||
92
CMake/FindLibssh.cmake
Normal file
92
CMake/FindLibssh.cmake
Normal file
@@ -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()
|
||||
80
CMake/FindLibssh2.cmake
Normal file
80
CMake/FindLibssh2.cmake
Normal file
@@ -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)
|
||||
88
CMake/FindLibuv.cmake
Normal file
88
CMake/FindLibuv.cmake
Normal file
@@ -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()
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
64
CMake/FindWolfSSH.cmake
Normal file
64
CMake/FindWolfSSH.cmake
Normal file
@@ -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)
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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@)
|
||||
|
||||
1631
CMakeLists.txt
1631
CMakeLists.txt
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
* ----------
|
||||
|
||||
@@ -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()
|
||||
|
||||
44
lib/altsvc.c
44
lib/altsvc.c
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
lib/bufq.c
69
lib/bufq.c
@@ -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.
|
||||
|
||||
319
lib/c-hyper.c
319
lib/c-hyper.c
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
148
lib/cf-socket.c
148
lib/cf-socket.c
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
/*
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
|
||||
1303
lib/conncache.c
1303
lib/conncache.c
File diff suppressed because it is too large
Load Diff
247
lib/conncache.h
247
lib/conncache.h
@@ -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 */
|
||||
|
||||
144
lib/connect.c
144
lib/connect.c
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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_":"",
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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}
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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().
|
||||
*
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
215
lib/curl_trc.c
215
lib/curl_trc.c
@@ -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) */
|
||||
|
||||
|
||||
43
lib/curlx.h
43
lib/curlx.h
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
525
lib/doh.c
525
lib/doh.c
@@ -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
lib/doh.h
59
lib/doh.h
@@ -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);
|
||||
|
||||
159
lib/easy.c
159
lib/easy.c
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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++;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
struct fileinfo {
|
||||
struct curl_fileinfo info;
|
||||
struct Curl_llist_element list;
|
||||
struct Curl_llist_node list;
|
||||
struct dynbuf buf;
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
116
lib/ftp.c
116
lib/ftp.c
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
78
lib/hash.c
78
lib/hash.c
@@ -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;
|
||||
|
||||
16
lib/hash.h
16
lib/hash.h
@@ -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 *));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.. */
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
93
lib/hostip.c
93
lib/hostip.c
@@ -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;
|
||||
}
|
||||
|
||||
21
lib/hostip.h
21
lib/hostip.h
@@ -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
|
||||
|
||||
@@ -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