mirror of
https://github.com/Kitware/CMake.git
synced 2026-05-06 22:30:07 -05:00
Merge topic 'update-curl'
b298ba708aUtilities: Update hard-coded try_compile results for curl 8.4.08a9fa27a35curl: Set build options the way we need for CMakedf4efb72e4Merge branch 'upstream-curl' into update-curle6a6c1abc1curl 2023-10-11 (d755a5f7)8f6a6b02e5curl: Update script to get curl 8.4.0 Acked-by: Kitware Robot <kwrobot@kitware.com> Acked-by: buildbot <buildbot@kitware.com> Merge-request: !8870
This commit is contained in:
@@ -8,7 +8,7 @@ readonly name="curl"
|
||||
readonly ownership="Curl Upstream <curl-library@lists.haxx.se>"
|
||||
readonly subtree="Utilities/cmcurl"
|
||||
readonly repo="https://github.com/curl/curl.git"
|
||||
readonly tag="curl-8_3_0"
|
||||
readonly tag="curl-8_4_0"
|
||||
readonly shortlog=false
|
||||
readonly paths="
|
||||
CMake/*
|
||||
|
||||
@@ -173,6 +173,7 @@ if(WIN32)
|
||||
set(HAVE_SIGNAL_H 1)
|
||||
set(HAVE_SIZEOF_ADDRESS_FAMILY 0)
|
||||
set(HAVE_SIZEOF_SA_FAMILY_T 0)
|
||||
set(HAVE_SIZEOF_SUSECONDS_T 0)
|
||||
set(HAVE_SOCKETPAIR 0)
|
||||
set(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 0)
|
||||
set(HAVE_SPAWN_H 0)
|
||||
|
||||
@@ -26,6 +26,12 @@ include(CheckCSourceCompiles)
|
||||
option(CURL_HIDDEN_SYMBOLS "Set to ON to hide libcurl internal symbols (=hide all symbols that aren't officially external)." ON)
|
||||
mark_as_advanced(CURL_HIDDEN_SYMBOLS)
|
||||
|
||||
if(WIN32 AND ENABLE_CURLDEBUG)
|
||||
# We need to export internal debug functions (e.g. curl_dbg_*), so disable
|
||||
# symbol hiding for debug builds.
|
||||
set(CURL_HIDDEN_SYMBOLS OFF)
|
||||
endif()
|
||||
|
||||
if(CURL_HIDDEN_SYMBOLS)
|
||||
set(SUPPORTS_SYMBOL_HIDING FALSE)
|
||||
|
||||
|
||||
@@ -21,23 +21,6 @@
|
||||
* SPDX-License-Identifier: curl
|
||||
*
|
||||
***************************************************************************/
|
||||
#ifdef TIME_WITH_SYS_TIME
|
||||
/* Time with sys/time test */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
if ((struct tm *) 0)
|
||||
return 0;
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FCNTL_O_NONBLOCK
|
||||
|
||||
|
||||
@@ -31,8 +31,10 @@ Find the ngtcp2 library
|
||||
This module accepts optional COMPONENTS to control the crypto library (these are
|
||||
mutually exclusive)::
|
||||
|
||||
OpenSSL: Use libngtcp2_crypto_quictls
|
||||
GnuTLS: Use libngtcp2_crypto_gnutls
|
||||
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
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#
|
||||
###########################################################################
|
||||
include(CheckCSourceCompiles)
|
||||
include(CheckCSourceRuns)
|
||||
|
||||
# The begin of the sources (macros and includes)
|
||||
set(_source_epilogue "#undef inline")
|
||||
|
||||
@@ -57,10 +59,9 @@ check_c_source_compiles("${_source_epilogue}
|
||||
|
||||
if(NOT HAVE_WINDOWS_H)
|
||||
add_header_include(HAVE_SYS_TIME_H "sys/time.h")
|
||||
add_header_include(TIME_WITH_SYS_TIME "time.h")
|
||||
add_header_include(HAVE_TIME_H "time.h")
|
||||
endif()
|
||||
check_c_source_compiles("${_source_epilogue}
|
||||
#include <time.h>
|
||||
int main(void) {
|
||||
struct timeval ts;
|
||||
ts.tv_sec = 0;
|
||||
@@ -90,7 +91,6 @@ if(NOT CMAKE_CROSSCOMPILING)
|
||||
# only try this on non-apple platforms
|
||||
|
||||
# if not cross-compilation...
|
||||
include(CheckCSourceRuns)
|
||||
set(CMAKE_REQUIRED_FLAGS "")
|
||||
if(HAVE_SYS_POLL_H)
|
||||
set(CMAKE_REQUIRED_FLAGS "-DHAVE_SYS_POLL_H")
|
||||
@@ -133,3 +133,89 @@ if(NOT CMAKE_CROSSCOMPILING)
|
||||
}" HAVE_POLL_FINE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Detect HAVE_GETADDRINFO_THREADSAFE
|
||||
|
||||
if(WIN32)
|
||||
set(HAVE_GETADDRINFO_THREADSAFE ${HAVE_GETADDRINFO})
|
||||
elseif(NOT HAVE_GETADDRINFO)
|
||||
set(HAVE_GETADDRINFO_THREADSAFE FALSE)
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "AIX" OR
|
||||
CMAKE_SYSTEM_NAME STREQUAL "Darwin" OR
|
||||
CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR
|
||||
CMAKE_SYSTEM_NAME STREQUAL "HP-UX" OR
|
||||
CMAKE_SYSTEM_NAME STREQUAL "MidnightBSD" OR
|
||||
CMAKE_SYSTEM_NAME STREQUAL "NetBSD" OR
|
||||
CMAKE_SYSTEM_NAME STREQUAL "SunOS")
|
||||
set(HAVE_GETADDRINFO_THREADSAFE TRUE)
|
||||
elseif(CMAKE_SYSTEM_NAME MATCHES "BSD")
|
||||
set(HAVE_GETADDRINFO_THREADSAFE FALSE)
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED HAVE_GETADDRINFO_THREADSAFE)
|
||||
|
||||
set(_save_epilogue "${_source_epilogue}")
|
||||
set(_source_epilogue "#undef inline")
|
||||
|
||||
add_header_include(HAVE_SYS_SOCKET_H "sys/socket.h")
|
||||
add_header_include(HAVE_SYS_TIME_H "sys/time.h")
|
||||
add_header_include(HAVE_NETDB_H "netdb.h")
|
||||
|
||||
check_c_source_compiles("${_source_epilogue}
|
||||
int main(void)
|
||||
{
|
||||
#ifdef h_errno
|
||||
return 0;
|
||||
#else
|
||||
force compilation error
|
||||
#endif
|
||||
}" HAVE_H_ERRNO)
|
||||
|
||||
if(NOT HAVE_H_ERRNO)
|
||||
check_c_source_runs("${_source_epilogue}
|
||||
int main(void)
|
||||
{
|
||||
h_errno = 2;
|
||||
return h_errno != 0 ? 1 : 0;
|
||||
}" HAVE_H_ERRNO_ASSIGNABLE)
|
||||
|
||||
if(NOT HAVE_H_ERRNO_ASSIGNABLE)
|
||||
check_c_source_compiles("${_source_epilogue}
|
||||
int main(void)
|
||||
{
|
||||
#if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200809L)
|
||||
return 0;
|
||||
#elif defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 700)
|
||||
return 0;
|
||||
#else
|
||||
force compilation error
|
||||
#endif
|
||||
}" HAVE_H_ERRNO_SBS_ISSUE_7)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(HAVE_H_ERRNO OR HAVE_H_ERRNO_ASSIGNABLE OR HAVE_H_ERRNO_SBS_ISSUE_7)
|
||||
set(HAVE_GETADDRINFO_THREADSAFE TRUE)
|
||||
endif()
|
||||
|
||||
set(_source_epilogue "${_save_epilogue}")
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED HAVE_CLOCK_GETTIME_MONOTONIC_RAW)
|
||||
set(_save_epilogue "${_source_epilogue}")
|
||||
set(_source_epilogue "#undef inline")
|
||||
|
||||
add_header_include(HAVE_SYS_TYPES_H "sys/types.h")
|
||||
add_header_include(HAVE_SYS_TIME_H "sys/time.h")
|
||||
|
||||
check_c_source_compiles("${_source_epilogue}
|
||||
#include <time.h>
|
||||
int main(void)
|
||||
{
|
||||
struct timespec ts;
|
||||
(void)clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
|
||||
return 0;
|
||||
}" HAVE_CLOCK_GETTIME_MONOTONIC_RAW)
|
||||
|
||||
set(_source_epilogue "${_save_epilogue}")
|
||||
endif()
|
||||
|
||||
@@ -33,6 +33,7 @@ if(NOT UNIX)
|
||||
set(HAVE_UNISTD_H 1)
|
||||
set(HAVE_INTTYPES_H 1)
|
||||
set(HAVE_STRTOLL 1)
|
||||
set(HAVE_BASENAME 1)
|
||||
elseif(MSVC)
|
||||
if(NOT MSVC_VERSION LESS 1800)
|
||||
set(HAVE_INTTYPES_H 1)
|
||||
@@ -46,30 +47,32 @@ if(NOT UNIX)
|
||||
else()
|
||||
set(HAVE_SNPRINTF 0)
|
||||
endif()
|
||||
set(HAVE_BASENAME 0)
|
||||
endif()
|
||||
|
||||
set(HAVE_LIBSOCKET 0)
|
||||
set(HAVE_GETHOSTNAME 1)
|
||||
set(HAVE_LIBZ 0)
|
||||
|
||||
set(HAVE_ARC4RANDOM 0)
|
||||
set(HAVE_FNMATCH 0)
|
||||
set(HAVE_SCHED_YIELD 0)
|
||||
set(HAVE_ARPA_INET_H 0)
|
||||
set(HAVE_ARPA_TFTP_H 0)
|
||||
set(HAVE_FCNTL_H 1)
|
||||
set(HAVE_IFADDRS_H 0)
|
||||
set(HAVE_IO_H 1)
|
||||
set(HAVE_NETDB_H 0)
|
||||
set(HAVE_NETINET_IN_H 0)
|
||||
set(HAVE_NETINET_TCP_H 0)
|
||||
set(HAVE_NETINET_UDP_H 0)
|
||||
set(HAVE_NET_IF_H 0)
|
||||
set(HAVE_IOCTL_SIOCGIFADDR 0)
|
||||
set(HAVE_POLL_H 0)
|
||||
set(HAVE_POLL_FINE 0)
|
||||
set(HAVE_PWD_H 0)
|
||||
set(HAVE_SETJMP_H 1)
|
||||
set(HAVE_SIGNAL_H 1)
|
||||
set(HAVE_STDLIB_H 1)
|
||||
set(HAVE_STRINGS_H 0)
|
||||
set(HAVE_STRING_H 1)
|
||||
set(HAVE_SYS_FILIO_H 0)
|
||||
set(HAVE_SYS_WAIT_H 0)
|
||||
set(HAVE_SYS_IOCTL_H 0)
|
||||
set(HAVE_SYS_PARAM_H 0)
|
||||
set(HAVE_SYS_POLL_H 0)
|
||||
@@ -84,14 +87,16 @@ if(NOT UNIX)
|
||||
set(HAVE_SYS_UTIME_H 1)
|
||||
set(HAVE_TERMIOS_H 0)
|
||||
set(HAVE_TERMIO_H 0)
|
||||
set(HAVE_TIME_H 1)
|
||||
set(HAVE_UTIME_H 0)
|
||||
|
||||
set(HAVE_FSEEKO 0)
|
||||
set(HAVE__FSEEKI64 1)
|
||||
set(HAVE_SOCKET 1)
|
||||
set(HAVE_SELECT 1)
|
||||
set(HAVE_STRDUP 1)
|
||||
set(HAVE_STRICMP 1)
|
||||
set(HAVE_STRCMPI 1)
|
||||
set(HAVE_MEMRCHR 0)
|
||||
set(HAVE_GETTIMEOFDAY 0)
|
||||
set(HAVE_CLOSESOCKET 1)
|
||||
set(HAVE_SIGSETJMP 0)
|
||||
@@ -101,11 +106,13 @@ if(NOT UNIX)
|
||||
set(HAVE_GETEUID 0)
|
||||
set(HAVE_UTIME 1)
|
||||
set(HAVE_GMTIME_R 0)
|
||||
set(HAVE_CLOCK_GETTIME_MONOTONIC_RAW 0)
|
||||
set(HAVE_GETHOSTBYNAME_R 0)
|
||||
set(HAVE_SIGNAL 1)
|
||||
set(HAVE_LINUX_TCP_H 0)
|
||||
set(HAVE_GLIBC_STRERROR_R 0)
|
||||
set(HAVE_MACH_ABSOLUTE_TIME 0)
|
||||
set(HAVE_GETIFADDRS 0)
|
||||
|
||||
set(HAVE_GETHOSTBYNAME_R_3 0)
|
||||
set(HAVE_GETHOSTBYNAME_R_3_REENTRANT 0)
|
||||
@@ -114,7 +121,6 @@ if(NOT UNIX)
|
||||
set(HAVE_GETHOSTBYNAME_R_6 0)
|
||||
set(HAVE_GETHOSTBYNAME_R_6_REENTRANT 0)
|
||||
|
||||
set(TIME_WITH_SYS_TIME 0)
|
||||
set(HAVE_O_NONBLOCK 0)
|
||||
set(HAVE_IN_ADDR_T 0)
|
||||
set(STDC_HEADERS 1)
|
||||
|
||||
+158
-111
@@ -54,6 +54,7 @@ set(CURL_DISABLE_SHUFFLE_DNS OFF)
|
||||
set(CURL_DISABLE_SMB OFF)
|
||||
set(CURL_DISABLE_SMTP ON CACHE INTERNAL "Disable curl smtp protocol?")
|
||||
set(CURL_DISABLE_SOCKETPAIR OFF)
|
||||
set(CURL_DISABLE_SRP OFF)
|
||||
set(CURL_DISABLE_TELNET ON CACHE INTERNAL "Disable curl telnet protocol?")
|
||||
set(CURL_DISABLE_TFTP ON CACHE INTERNAL "Disable curl tftp protocol?")
|
||||
set(CURL_DISABLE_VERBOSE_STRINGS OFF CACHE INTERNAL "Do not disable curl verbosity")
|
||||
@@ -203,9 +204,9 @@ endif()
|
||||
# https://cmake.org/cmake/help/latest/module/FetchContent.html#integrating-with-find-package
|
||||
#
|
||||
# The following variables are available:
|
||||
# HAVE_SSL_SET0_WBIO: `SSL_set0_wbio` present in OpenSSL
|
||||
# HAVE_AWSLC: OpenSSL is AWS-LC
|
||||
# HAVE_BORINGSSL: OpenSSL is BoringSSL
|
||||
# HAVE_SSL_SET0_WBIO: `SSL_set0_wbio` present in OpenSSL/wolfSSL
|
||||
# HAVE_OPENSSL_SRP: `SSL_CTX_set_srp_username` present in OpenSSL/wolfSSL
|
||||
# HAVE_GNUTLS_SRP: `gnutls_srp_verifier` present in GnuTLS
|
||||
# HAVE_SSL_CTX_SET_QUIC_METHOD: `SSL_CTX_set_quic_method` present in OpenSSL/wolfSSL
|
||||
# HAVE_QUICHE_CONN_SET_QLOG_FD: `quiche_conn_set_qlog_fd` present in QUICHE
|
||||
# HAVE_ZSTD_CREATEDSTREAM: `ZSTD_createDStream` present in Zstd
|
||||
@@ -256,7 +257,7 @@ option(CURL_WERROR "Turn compiler warnings into errors" OFF)
|
||||
option(PICKY_COMPILER "Enable picky compiler options" ON)
|
||||
option(BUILD_CURL_EXE "Set to ON to build curl executable." ON)
|
||||
option(BUILD_SHARED_LIBS "Build shared libraries" ON)
|
||||
option(BUILD_STATIC_LIBS "Build shared libraries" OFF)
|
||||
option(BUILD_STATIC_LIBS "Build static libraries" OFF)
|
||||
option(BUILD_STATIC_CURL "Build curl executable with static libcurl" OFF)
|
||||
option(ENABLE_ARES "Set to ON to enable c-ares support" OFF)
|
||||
if(WIN32)
|
||||
@@ -351,6 +352,8 @@ mark_as_advanced(CURL_ENABLE_EXPORT_TARGET)
|
||||
|
||||
option(CURL_DISABLE_ALTSVC "disables alt-svc support" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_ALTSVC)
|
||||
option(CURL_DISABLE_SRP "disables TLS-SRP support" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_SRP)
|
||||
option(CURL_DISABLE_COOKIES "disables cookies support" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_COOKIES)
|
||||
option(CURL_DISABLE_BASIC_AUTH "disables Basic authentication" OFF)
|
||||
@@ -466,7 +469,7 @@ if(ENABLE_IPV6 AND NOT WIN32)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND NOT ENABLE_ARES)
|
||||
set(use_core_foundation ON)
|
||||
set(use_core_foundation_and_core_services ON)
|
||||
|
||||
find_library(SYSTEMCONFIGURATION_FRAMEWORK "SystemConfiguration")
|
||||
if(NOT SYSTEMCONFIGURATION_FRAMEWORK)
|
||||
@@ -551,25 +554,16 @@ if(WIN32)
|
||||
if(USE_LIBRTMP)
|
||||
list(APPEND CURL_LIBS "winmm")
|
||||
endif()
|
||||
|
||||
# Matching logic used for Curl_win32_random()
|
||||
if(MINGW)
|
||||
check_c_source_compiles("
|
||||
#include <_mingw.h>
|
||||
#if defined(__MINGW64_VERSION_MAJOR)
|
||||
#error
|
||||
#endif
|
||||
int main(void) {
|
||||
return 0;
|
||||
}"
|
||||
HAVE_MINGW_ORIGINAL)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(0) # This code not needed for building within CMake.
|
||||
# check SSL libraries
|
||||
option(CURL_ENABLE_SSL "Enable SSL support" ON)
|
||||
|
||||
if(CURL_DEFAULT_SSL_BACKEND)
|
||||
set(valid_default_ssl_backend FALSE)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
cmake_dependent_option(CURL_USE_SECTRANSP "Enable Apple OS native SSL/TLS" OFF CURL_ENABLE_SSL OFF)
|
||||
endif()
|
||||
@@ -581,7 +575,7 @@ endif()
|
||||
cmake_dependent_option(CURL_USE_MBEDTLS "Enable mbedTLS for SSL/TLS" OFF CURL_ENABLE_SSL OFF)
|
||||
cmake_dependent_option(CURL_USE_BEARSSL "Enable BearSSL for SSL/TLS" OFF CURL_ENABLE_SSL OFF)
|
||||
cmake_dependent_option(CURL_USE_WOLFSSL "Enable wolfSSL for SSL/TLS" OFF CURL_ENABLE_SSL OFF)
|
||||
cmake_dependent_option(CURL_USE_GNUTLS "Enable GNUTLS for SSL/TLS" OFF CURL_ENABLE_SSL OFF)
|
||||
cmake_dependent_option(CURL_USE_GNUTLS "Enable GnuTLS for SSL/TLS" OFF CURL_ENABLE_SSL OFF)
|
||||
|
||||
set(openssl_default ON)
|
||||
if(WIN32 OR CURL_USE_SECTRANSP OR CURL_USE_SCHANNEL OR CURL_USE_MBEDTLS OR CURL_USE_WOLFSSL)
|
||||
@@ -607,13 +601,17 @@ if(CURL_USE_SCHANNEL)
|
||||
set(SSL_ENABLED ON)
|
||||
set(USE_SCHANNEL ON) # Windows native SSL/TLS support
|
||||
set(USE_WINDOWS_SSPI ON) # CURL_USE_SCHANNEL implies CURL_WINDOWS_SSPI
|
||||
|
||||
if(CURL_DEFAULT_SSL_BACKEND AND CURL_DEFAULT_SSL_BACKEND STREQUAL "schannel")
|
||||
set(valid_default_ssl_backend TRUE)
|
||||
endif()
|
||||
endif()
|
||||
if(CURL_WINDOWS_SSPI)
|
||||
set(USE_WINDOWS_SSPI ON)
|
||||
endif()
|
||||
|
||||
if(CURL_USE_SECTRANSP)
|
||||
set(use_core_foundation ON)
|
||||
set(use_core_foundation_and_core_services ON)
|
||||
|
||||
find_library(SECURITY_FRAMEWORK "Security")
|
||||
if(NOT SECURITY_FRAMEWORK)
|
||||
@@ -623,15 +621,24 @@ if(CURL_USE_SECTRANSP)
|
||||
set(SSL_ENABLED ON)
|
||||
set(USE_SECTRANSP ON)
|
||||
list(APPEND CURL_LIBS "-framework Security")
|
||||
|
||||
if(CURL_DEFAULT_SSL_BACKEND AND CURL_DEFAULT_SSL_BACKEND STREQUAL "secure-transport")
|
||||
set(valid_default_ssl_backend TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(use_core_foundation)
|
||||
if(use_core_foundation_and_core_services)
|
||||
find_library(COREFOUNDATION_FRAMEWORK "CoreFoundation")
|
||||
find_library(CORESERVICES_FRAMEWORK "CoreServices")
|
||||
|
||||
if(NOT COREFOUNDATION_FRAMEWORK)
|
||||
message(FATAL_ERROR "CoreFoundation framework not found")
|
||||
endif()
|
||||
if(NOT CORESERVICES_FRAMEWORK)
|
||||
message(FATAL_ERROR "CoreServices framework not found")
|
||||
endif()
|
||||
|
||||
list(APPEND CURL_LIBS "-framework CoreFoundation")
|
||||
list(APPEND CURL_LIBS "-framework CoreFoundation -framework CoreServices")
|
||||
endif()
|
||||
|
||||
if(CURL_USE_OPENSSL)
|
||||
@@ -648,9 +655,11 @@ if(CURL_USE_OPENSSL)
|
||||
|
||||
if(WIN32)
|
||||
list(APPEND CURL_LIBS "ws2_32")
|
||||
if(NOT HAVE_MINGW_ORIGINAL)
|
||||
list(APPEND CURL_LIBS "bcrypt") # for OpenSSL/LibreSSL
|
||||
endif()
|
||||
list(APPEND CURL_LIBS "bcrypt") # for OpenSSL/LibreSSL
|
||||
endif()
|
||||
|
||||
if(CURL_DEFAULT_SSL_BACKEND AND CURL_DEFAULT_SSL_BACKEND STREQUAL "openssl")
|
||||
set(valid_default_ssl_backend TRUE)
|
||||
endif()
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
@@ -677,6 +686,10 @@ if(CURL_USE_MBEDTLS)
|
||||
set(USE_MBEDTLS ON)
|
||||
list(APPEND CURL_LIBS ${MBEDTLS_LIBRARIES})
|
||||
include_directories(${MBEDTLS_INCLUDE_DIRS})
|
||||
|
||||
if(CURL_DEFAULT_SSL_BACKEND AND CURL_DEFAULT_SSL_BACKEND STREQUAL "mbedtls")
|
||||
set(valid_default_ssl_backend TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CURL_USE_BEARSSL)
|
||||
@@ -685,6 +698,10 @@ if(CURL_USE_BEARSSL)
|
||||
set(USE_BEARSSL ON)
|
||||
list(APPEND CURL_LIBS ${BEARSSL_LIBRARY})
|
||||
include_directories(${BEARSSL_INCLUDE_DIRS})
|
||||
|
||||
if(CURL_DEFAULT_SSL_BACKEND AND CURL_DEFAULT_SSL_BACKEND STREQUAL "bearssl")
|
||||
set(valid_default_ssl_backend TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CURL_USE_WOLFSSL)
|
||||
@@ -693,11 +710,34 @@ if(CURL_USE_WOLFSSL)
|
||||
set(USE_WOLFSSL ON)
|
||||
list(APPEND CURL_LIBS ${WolfSSL_LIBRARIES})
|
||||
include_directories(${WolfSSL_INCLUDE_DIRS})
|
||||
|
||||
if(CURL_DEFAULT_SSL_BACKEND AND CURL_DEFAULT_SSL_BACKEND STREQUAL "wolfssl")
|
||||
set(valid_default_ssl_backend TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CURL_USE_GNUTLS)
|
||||
set(SSL_ENABLED ON)
|
||||
set(USE_GNUTLS ON)
|
||||
find_package(GnuTLS REQUIRED)
|
||||
set(SSL_ENABLED ON)
|
||||
set(USE_GNUTLS ON)
|
||||
list(APPEND CURL_LIBS ${GNUTLS_LIBRARIES} "nettle")
|
||||
include_directories(${GNUTLS_INCLUDE_DIRS})
|
||||
|
||||
if(CURL_DEFAULT_SSL_BACKEND AND CURL_DEFAULT_SSL_BACKEND STREQUAL "gnutls")
|
||||
set(valid_default_ssl_backend TRUE)
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED HAVE_GNUTLS_SRP AND NOT CURL_DISABLE_SRP)
|
||||
cmake_push_check_state()
|
||||
set(CMAKE_REQUIRED_INCLUDES ${GNUTLS_INCLUDE_DIRS})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${GNUTLS_LIBRARIES})
|
||||
check_symbol_exists(gnutls_srp_verifier "gnutls/gnutls.h" HAVE_GNUTLS_SRP)
|
||||
cmake_pop_check_state()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CURL_DEFAULT_SSL_BACKEND AND NOT valid_default_ssl_backend)
|
||||
message(FATAL_ERROR "CURL_DEFAULT_SSL_BACKEND '${CURL_DEFAULT_SSL_BACKEND}' not enabled.")
|
||||
endif()
|
||||
|
||||
# Keep ZLIB detection after TLS detection,
|
||||
@@ -743,7 +783,7 @@ option(CURL_ZSTD "Set to ON to enable building curl with zstd support." OFF)
|
||||
set(HAVE_ZSTD OFF)
|
||||
if(CURL_ZSTD)
|
||||
find_package(Zstd REQUIRED)
|
||||
if (NOT DEFINED HAVE_ZSTD_CREATEDSTREAM)
|
||||
if(NOT DEFINED HAVE_ZSTD_CREATEDSTREAM)
|
||||
cmake_push_check_state()
|
||||
set(CMAKE_REQUIRED_INCLUDES ${Zstd_INCLUDE_DIRS})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${Zstd_LIBRARIES})
|
||||
@@ -768,9 +808,7 @@ macro(openssl_check_symbol_exists SYMBOL FILES VARIABLE)
|
||||
endif()
|
||||
if(WIN32)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES "ws2_32")
|
||||
if(NOT HAVE_MINGW_ORIGINAL)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES "bcrypt") # for OpenSSL/LibreSSL
|
||||
endif()
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES "bcrypt") # for OpenSSL/LibreSSL
|
||||
endif()
|
||||
elseif(USE_WOLFSSL)
|
||||
set(CMAKE_REQUIRED_INCLUDES "${WolfSSL_INCLUDE_DIRS}")
|
||||
@@ -792,6 +830,9 @@ if(USE_OPENSSL OR USE_WOLFSSL)
|
||||
if(NOT DEFINED HAVE_SSL_SET0_WBIO)
|
||||
openssl_check_symbol_exists(SSL_set0_wbio "openssl/ssl.h" HAVE_SSL_SET0_WBIO)
|
||||
endif()
|
||||
if(NOT DEFINED HAVE_OPENSSL_SRP AND NOT CURL_DISABLE_SRP)
|
||||
openssl_check_symbol_exists(SSL_CTX_set_srp_username "openssl/ssl.h" HAVE_OPENSSL_SRP)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(USE_NGHTTP2 "Use nghttp2 library" OFF)
|
||||
@@ -806,7 +847,7 @@ if(USE_NGTCP2)
|
||||
if(USE_OPENSSL OR USE_WOLFSSL)
|
||||
if(USE_WOLFSSL)
|
||||
find_package(NGTCP2 REQUIRED wolfSSL)
|
||||
elseif(HAVE_BORINGSSL)
|
||||
elseif(HAVE_BORINGSSL OR HAVE_AWSLC)
|
||||
find_package(NGTCP2 REQUIRED BoringSSL)
|
||||
else()
|
||||
find_package(NGTCP2 REQUIRED quictls)
|
||||
@@ -823,9 +864,7 @@ if(USE_NGTCP2)
|
||||
if(NOT HAVE_SSL_CTX_SET_QUIC_METHOD)
|
||||
message(FATAL_ERROR "QUIC support is missing in OpenSSL/LibreSSL/BoringSSL/wolfSSL. Try setting -DOPENSSL_ROOT_DIR")
|
||||
endif()
|
||||
|
||||
elseif(USE_GNUTLS)
|
||||
# TODO add GnuTLS support as vtls library.
|
||||
find_package(NGTCP2 REQUIRED GnuTLS)
|
||||
else()
|
||||
message(FATAL_ERROR "ngtcp2 requires OpenSSL, wolfSSL or GnuTLS")
|
||||
@@ -869,6 +908,10 @@ if(USE_MSH3)
|
||||
list(APPEND CURL_LIBS ${MSH3_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(NOT CURL_DISABLE_SRP AND (HAVE_GNUTLS_SRP OR HAVE_OPENSSL_SRP))
|
||||
set(USE_TLS_SRP 1)
|
||||
endif()
|
||||
|
||||
if(NOT CURL_DISABLE_LDAP)
|
||||
if(WIN32)
|
||||
option(USE_WIN32_LDAP "Use Windows LDAP implementation" ON)
|
||||
@@ -880,15 +923,9 @@ if(NOT CURL_DISABLE_LDAP)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(CURL_USE_OPENLDAP "Use OpenLDAP code." OFF)
|
||||
mark_as_advanced(CURL_USE_OPENLDAP)
|
||||
set(CMAKE_LDAP_LIB "ldap" CACHE STRING "Name or full path to ldap library")
|
||||
set(CMAKE_LBER_LIB "lber" CACHE STRING "Name or full path to lber library")
|
||||
|
||||
if(CURL_USE_OPENLDAP AND USE_WIN32_LDAP)
|
||||
message(FATAL_ERROR "Cannot use USE_WIN32_LDAP and CURL_USE_OPENLDAP at the same time")
|
||||
endif()
|
||||
|
||||
# Now that we know, we're not using windows LDAP...
|
||||
if(NOT USE_WIN32_LDAP)
|
||||
# Check for LDAP
|
||||
@@ -913,9 +950,6 @@ if(NOT CURL_DISABLE_LDAP)
|
||||
set(CURL_DISABLE_LDAP ON CACHE BOOL "" FORCE)
|
||||
set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES_BAK}) #LDAP includes won't be used
|
||||
else()
|
||||
if(CURL_USE_OPENLDAP)
|
||||
set(USE_OPENLDAP ON)
|
||||
endif()
|
||||
if(CMAKE_LDAP_INCLUDE_DIR)
|
||||
include_directories(${CMAKE_LDAP_INCLUDE_DIR})
|
||||
endif()
|
||||
@@ -929,13 +963,18 @@ if(NOT CURL_DISABLE_LDAP)
|
||||
endif()
|
||||
list(APPEND _HEADER_LIST "ldap.h")
|
||||
|
||||
set(_SRC_STRING "")
|
||||
set(_INCLUDE_STRING "")
|
||||
foreach(_HEADER ${_HEADER_LIST})
|
||||
set(_INCLUDE_STRING "${_INCLUDE_STRING}#include <${_HEADER}>\n")
|
||||
endforeach()
|
||||
|
||||
set(_SRC_STRING
|
||||
"
|
||||
list(APPEND CMAKE_REQUIRED_DEFINITIONS -DLDAP_DEPRECATED=1)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES ${CMAKE_LDAP_LIB})
|
||||
if(HAVE_LIBLBER)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES ${CMAKE_LBER_LIB})
|
||||
endif()
|
||||
|
||||
check_c_source_compiles("
|
||||
${_INCLUDE_STRING}
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
@@ -943,21 +982,27 @@ if(NOT CURL_DISABLE_LDAP)
|
||||
BerElement *bep = ber_init(bvp);
|
||||
ber_free(bep, 1);
|
||||
return 0;
|
||||
}"
|
||||
)
|
||||
list(APPEND CMAKE_REQUIRED_DEFINITIONS -DLDAP_DEPRECATED=1)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES ${CMAKE_LDAP_LIB})
|
||||
if(HAVE_LIBLBER)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES ${CMAKE_LBER_LIB})
|
||||
endif()
|
||||
check_c_source_compiles("${_SRC_STRING}" NOT_NEED_LBER_H)
|
||||
unset(CMAKE_REQUIRED_LIBRARIES)
|
||||
|
||||
}" NOT_NEED_LBER_H)
|
||||
if(NOT_NEED_LBER_H)
|
||||
set(NEED_LBER_H OFF)
|
||||
else()
|
||||
set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -DNEED_LBER_H")
|
||||
endif()
|
||||
|
||||
check_function_exists(ldap_url_parse HAVE_LDAP_URL_PARSE)
|
||||
check_function_exists(ldap_init_fd HAVE_LDAP_INIT_FD)
|
||||
|
||||
unset(CMAKE_REQUIRED_LIBRARIES)
|
||||
|
||||
check_include_file("ldap_ssl.h" HAVE_LDAP_SSL_H)
|
||||
|
||||
if(HAVE_LDAP_INIT_FD)
|
||||
set(USE_OPENLDAP ON)
|
||||
add_definitions("-DLDAP_DEPRECATED=1")
|
||||
endif()
|
||||
if(NOT CURL_DISABLE_LDAPS)
|
||||
set(HAVE_LDAP_SSL ON)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
@@ -970,10 +1015,6 @@ if(CURL_DISABLE_LDAP)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT CURL_DISABLE_LDAPS)
|
||||
check_include_file_concat("ldap_ssl.h" HAVE_LDAP_SSL_H)
|
||||
endif()
|
||||
|
||||
# Check for idn2
|
||||
option(USE_LIBIDN2 "Use libidn2 for IDN support" ON)
|
||||
if(USE_LIBIDN2)
|
||||
@@ -1180,9 +1221,13 @@ elseif(CURL_CA_PATH_AUTODETECT OR CURL_CA_BUNDLE_AUTODETECT)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CURL_CA_PATH_SET AND NOT USE_OPENSSL AND NOT USE_MBEDTLS)
|
||||
if(CURL_CA_PATH_SET AND
|
||||
NOT USE_OPENSSL AND
|
||||
NOT USE_WOLFSSL AND
|
||||
NOT USE_GNUTLS AND
|
||||
NOT USE_MBEDTLS)
|
||||
message(STATUS
|
||||
"CA path only supported by OpenSSL, GnuTLS or mbed TLS. "
|
||||
"CA path only supported by OpenSSL, wolfSSL, GnuTLS or mbedTLS. "
|
||||
"Set CURL_CA_PATH=none or enable one of those TLS backends.")
|
||||
endif()
|
||||
endif()
|
||||
@@ -1200,6 +1245,7 @@ endif()
|
||||
|
||||
check_include_file_concat("inttypes.h" HAVE_INTTYPES_H)
|
||||
check_include_file_concat("sys/filio.h" HAVE_SYS_FILIO_H)
|
||||
check_include_file_concat("sys/wait.h" HAVE_SYS_WAIT_H)
|
||||
check_include_file_concat("sys/ioctl.h" HAVE_SYS_IOCTL_H)
|
||||
check_include_file_concat("sys/param.h" HAVE_SYS_PARAM_H)
|
||||
check_include_file_concat("sys/poll.h" HAVE_SYS_POLL_H)
|
||||
@@ -1214,7 +1260,6 @@ check_include_file_concat("sys/un.h" HAVE_SYS_UN_H)
|
||||
check_include_file_concat("sys/utime.h" HAVE_SYS_UTIME_H)
|
||||
check_include_file_concat("sys/xattr.h" HAVE_SYS_XATTR_H)
|
||||
check_include_file_concat("arpa/inet.h" HAVE_ARPA_INET_H)
|
||||
check_include_file_concat("arpa/tftp.h" HAVE_ARPA_TFTP_H)
|
||||
check_include_file_concat("fcntl.h" HAVE_FCNTL_H)
|
||||
check_include_file_concat("idn2.h" HAVE_IDN2_H)
|
||||
check_include_file_concat("ifaddrs.h" HAVE_IFADDRS_H)
|
||||
@@ -1225,30 +1270,29 @@ check_include_file_concat("net/if.h" HAVE_NET_IF_H)
|
||||
check_include_file_concat("netdb.h" HAVE_NETDB_H)
|
||||
check_include_file_concat("netinet/in.h" HAVE_NETINET_IN_H)
|
||||
check_include_file_concat("netinet/tcp.h" HAVE_NETINET_TCP_H)
|
||||
check_include_file_concat("netinet/udp.h" HAVE_NETINET_UDP_H)
|
||||
check_include_file("linux/tcp.h" HAVE_LINUX_TCP_H)
|
||||
|
||||
check_include_file_concat("poll.h" HAVE_POLL_H)
|
||||
check_include_file_concat("pwd.h" HAVE_PWD_H)
|
||||
check_include_file_concat("setjmp.h" HAVE_SETJMP_H)
|
||||
check_include_file_concat("signal.h" HAVE_SIGNAL_H)
|
||||
check_include_file_concat("stdatomic.h" HAVE_STDATOMIC_H)
|
||||
check_include_file_concat("stdbool.h" HAVE_STDBOOL_H)
|
||||
check_include_file_concat("stdint.h" HAVE_STDINT_H)
|
||||
check_include_file_concat("stdlib.h" HAVE_STDLIB_H)
|
||||
check_include_file_concat("string.h" HAVE_STRING_H)
|
||||
check_include_file_concat("strings.h" HAVE_STRINGS_H)
|
||||
check_include_file_concat("stropts.h" HAVE_STROPTS_H)
|
||||
check_include_file_concat("termio.h" HAVE_TERMIO_H)
|
||||
check_include_file_concat("termios.h" HAVE_TERMIOS_H)
|
||||
check_include_file_concat("time.h" HAVE_TIME_H)
|
||||
check_include_file_concat("unistd.h" HAVE_UNISTD_H)
|
||||
check_include_file_concat("utime.h" HAVE_UTIME_H)
|
||||
|
||||
check_include_file_concat("stddef.h" HAVE_STDDEF_H)
|
||||
|
||||
check_type_size(size_t SIZEOF_SIZE_T)
|
||||
check_type_size(ssize_t SIZEOF_SSIZE_T)
|
||||
check_type_size("time_t" SIZEOF_TIME_T)
|
||||
check_type_size("suseconds_t" SIZEOF_SUSECONDS_T)
|
||||
|
||||
if(SIZEOF_SUSECONDS_T)
|
||||
set(HAVE_SUSECONDS_T 1)
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_CROSSCOMPILING)
|
||||
find_file(RANDOM_FILE urandom /dev)
|
||||
@@ -1265,45 +1309,50 @@ elseif(HAVE_LIBNETWORK)
|
||||
endif()
|
||||
|
||||
check_symbol_exists(fchmod "${CURL_INCLUDES}" HAVE_FCHMOD)
|
||||
check_symbol_exists(basename "${CURL_INCLUDES}" HAVE_BASENAME)
|
||||
check_symbol_exists(fnmatch "${CURL_INCLUDES};fnmatch.h" HAVE_FNMATCH)
|
||||
check_symbol_exists(basename "${CURL_INCLUDES};string.h" HAVE_BASENAME)
|
||||
check_symbol_exists(socket "${CURL_INCLUDES}" HAVE_SOCKET)
|
||||
check_symbol_exists(sched_yield "${CURL_INCLUDES};sched.h" HAVE_SCHED_YIELD)
|
||||
check_symbol_exists(socketpair "${CURL_INCLUDES}" HAVE_SOCKETPAIR)
|
||||
check_symbol_exists(recv "${CURL_INCLUDES}" HAVE_RECV)
|
||||
check_symbol_exists(send "${CURL_INCLUDES}" HAVE_SEND)
|
||||
check_symbol_exists(sendmsg "${CURL_INCLUDES}" HAVE_SENDMSG)
|
||||
check_symbol_exists(select "${CURL_INCLUDES}" HAVE_SELECT)
|
||||
check_symbol_exists(strdup "${CURL_INCLUDES}" HAVE_STRDUP)
|
||||
check_symbol_exists(strtok_r "${CURL_INCLUDES}" HAVE_STRTOK_R)
|
||||
check_symbol_exists(strcasecmp "${CURL_INCLUDES}" HAVE_STRCASECMP)
|
||||
check_symbol_exists(stricmp "${CURL_INCLUDES}" HAVE_STRICMP)
|
||||
check_symbol_exists(strcmpi "${CURL_INCLUDES}" HAVE_STRCMPI)
|
||||
check_symbol_exists(strdup "${CURL_INCLUDES};string.h" HAVE_STRDUP)
|
||||
check_symbol_exists(strtok_r "${CURL_INCLUDES};string.h" HAVE_STRTOK_R)
|
||||
check_symbol_exists(strcasecmp "${CURL_INCLUDES};string.h" HAVE_STRCASECMP)
|
||||
check_symbol_exists(stricmp "${CURL_INCLUDES};string.h" HAVE_STRICMP)
|
||||
check_symbol_exists(strcmpi "${CURL_INCLUDES};string.h" HAVE_STRCMPI)
|
||||
check_symbol_exists(memrchr "${CURL_INCLUDES};string.h" HAVE_MEMRCHR)
|
||||
check_symbol_exists(alarm "${CURL_INCLUDES}" HAVE_ALARM)
|
||||
check_symbol_exists(arc4random "${CURL_INCLUDES};stdlib.h" HAVE_ARC4RANDOM)
|
||||
check_symbol_exists(fcntl "${CURL_INCLUDES}" HAVE_FCNTL)
|
||||
check_symbol_exists(getppid "${CURL_INCLUDES}" HAVE_GETPPID)
|
||||
check_symbol_exists(utimes "${CURL_INCLUDES}" HAVE_UTIMES)
|
||||
|
||||
check_symbol_exists(gettimeofday "${CURL_INCLUDES}" HAVE_GETTIMEOFDAY)
|
||||
check_symbol_exists(closesocket "${CURL_INCLUDES}" HAVE_CLOSESOCKET)
|
||||
check_symbol_exists(sigsetjmp "${CURL_INCLUDES}" HAVE_SIGSETJMP)
|
||||
check_symbol_exists(sigsetjmp "${CURL_INCLUDES};setjmp.h" HAVE_SIGSETJMP)
|
||||
check_symbol_exists(getpass_r "${CURL_INCLUDES}" HAVE_GETPASS_R)
|
||||
check_symbol_exists(getpwuid "${CURL_INCLUDES}" HAVE_GETPWUID)
|
||||
check_symbol_exists(getpwuid_r "${CURL_INCLUDES}" HAVE_GETPWUID_R)
|
||||
check_symbol_exists(geteuid "${CURL_INCLUDES}" HAVE_GETEUID)
|
||||
check_symbol_exists(utime "${CURL_INCLUDES}" HAVE_UTIME)
|
||||
check_symbol_exists(gmtime_r "${CURL_INCLUDES}" HAVE_GMTIME_R)
|
||||
check_symbol_exists(gmtime_r "${CURL_INCLUDES};stdlib.h;time.h" HAVE_GMTIME_R)
|
||||
|
||||
check_symbol_exists(gethostbyname_r "${CURL_INCLUDES}" HAVE_GETHOSTBYNAME_R)
|
||||
|
||||
check_symbol_exists(signal "${CURL_INCLUDES}" HAVE_SIGNAL)
|
||||
check_symbol_exists(strtoll "${CURL_INCLUDES}" HAVE_STRTOLL)
|
||||
check_symbol_exists(strerror_r "${CURL_INCLUDES}" HAVE_STRERROR_R)
|
||||
check_symbol_exists(siginterrupt "${CURL_INCLUDES}" HAVE_SIGINTERRUPT)
|
||||
check_symbol_exists(getaddrinfo "${CURL_INCLUDES}" HAVE_GETADDRINFO)
|
||||
if(WIN32)
|
||||
set(HAVE_GETADDRINFO_THREADSAFE ${HAVE_GETADDRINFO})
|
||||
endif()
|
||||
check_symbol_exists(signal "${CURL_INCLUDES};signal.h" HAVE_SIGNAL)
|
||||
check_symbol_exists(strtoll "${CURL_INCLUDES};stdlib.h" HAVE_STRTOLL)
|
||||
check_symbol_exists(strerror_r "${CURL_INCLUDES};stdlib.h;string.h" HAVE_STRERROR_R)
|
||||
check_symbol_exists(siginterrupt "${CURL_INCLUDES};signal.h" HAVE_SIGINTERRUPT)
|
||||
check_symbol_exists(getaddrinfo "${CURL_INCLUDES};stdlib.h;string.h" HAVE_GETADDRINFO)
|
||||
check_symbol_exists(getifaddrs "${CURL_INCLUDES};stdlib.h" HAVE_GETIFADDRS)
|
||||
check_symbol_exists(freeaddrinfo "${CURL_INCLUDES}" HAVE_FREEADDRINFO)
|
||||
check_symbol_exists(pipe "${CURL_INCLUDES}" HAVE_PIPE)
|
||||
check_symbol_exists(ftruncate "${CURL_INCLUDES}" HAVE_FTRUNCATE)
|
||||
check_symbol_exists(fseeko "${CURL_INCLUDES};stdio.h" HAVE_FSEEKO)
|
||||
check_symbol_exists(_fseeki64 "${CURL_INCLUDES};stdio.h" HAVE__FSEEKI64)
|
||||
check_symbol_exists(getpeername "${CURL_INCLUDES}" HAVE_GETPEERNAME)
|
||||
check_symbol_exists(getsockname "${CURL_INCLUDES}" HAVE_GETSOCKNAME)
|
||||
check_symbol_exists(if_nametoindex "${CURL_INCLUDES}" HAVE_IF_NAMETOINDEX)
|
||||
@@ -1317,11 +1366,11 @@ if(NOT MSVC OR (MSVC_VERSION GREATER_EQUAL 1900))
|
||||
check_symbol_exists(snprintf "stdio.h" HAVE_SNPRINTF)
|
||||
endif()
|
||||
check_function_exists(mach_absolute_time HAVE_MACH_ABSOLUTE_TIME)
|
||||
check_symbol_exists(inet_ntop "${CURL_INCLUDES}" HAVE_INET_NTOP)
|
||||
check_symbol_exists(inet_ntop "${CURL_INCLUDES};stdlib.h;string.h" HAVE_INET_NTOP)
|
||||
if(MSVC AND (MSVC_VERSION LESS_EQUAL 1600))
|
||||
set(HAVE_INET_NTOP OFF)
|
||||
endif()
|
||||
check_symbol_exists(inet_pton "${CURL_INCLUDES}" HAVE_INET_PTON)
|
||||
check_symbol_exists(inet_pton "${CURL_INCLUDES};stdlib.h;string.h" HAVE_INET_PTON)
|
||||
|
||||
check_symbol_exists(fsetxattr "${CURL_INCLUDES}" HAVE_FSETXATTR)
|
||||
if(HAVE_FSETXATTR)
|
||||
@@ -1342,24 +1391,15 @@ set(CMAKE_EXTRA_INCLUDE_FILES "")
|
||||
|
||||
# sigaction and sigsetjmp are special. Use special mechanism for
|
||||
# detecting those, but only if previous attempt failed.
|
||||
if(HAVE_SIGNAL_H)
|
||||
check_symbol_exists(sigaction "signal.h" HAVE_SIGACTION)
|
||||
endif()
|
||||
check_symbol_exists(sigaction "signal.h" HAVE_SIGACTION)
|
||||
|
||||
if(NOT HAVE_SIGSETJMP)
|
||||
if(HAVE_SETJMP_H)
|
||||
check_symbol_exists(sigsetjmp "setjmp.h" HAVE_MACRO_SIGSETJMP)
|
||||
if(HAVE_MACRO_SIGSETJMP)
|
||||
set(HAVE_SIGSETJMP 1)
|
||||
endif()
|
||||
check_symbol_exists(sigsetjmp "setjmp.h" HAVE_MACRO_SIGSETJMP)
|
||||
if(HAVE_MACRO_SIGSETJMP)
|
||||
set(HAVE_SIGSETJMP 1)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# If there is no stricmp(), do not allow LDAP to parse URLs
|
||||
if(NOT HAVE_STRICMP)
|
||||
set(HAVE_LDAP_URL_PARSE 1)
|
||||
endif()
|
||||
|
||||
# Do curl specific tests
|
||||
foreach(CURL_TEST
|
||||
HAVE_FCNTL_O_NONBLOCK
|
||||
@@ -1370,7 +1410,6 @@ foreach(CURL_TEST
|
||||
HAVE_IOCTL_FIONBIO
|
||||
HAVE_IOCTL_SIOCGIFADDR
|
||||
HAVE_SETSOCKOPT_SO_NONBLOCK
|
||||
TIME_WITH_SYS_TIME
|
||||
HAVE_O_NONBLOCK
|
||||
HAVE_GETHOSTBYNAME_R_3
|
||||
HAVE_GETHOSTBYNAME_R_5
|
||||
@@ -1415,6 +1454,20 @@ if(WIN32)
|
||||
unset(HAVE_WIN32_WINNT CACHE)
|
||||
endif()
|
||||
|
||||
if(0) # This code not needed for building within CMake.
|
||||
if(NOT WIN32 AND NOT CMAKE_CROSSCOMPILING)
|
||||
# on not-Windows and not-crosscompiling, check for writable argv[]
|
||||
include(CheckCSourceRuns)
|
||||
check_c_source_runs("
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
argv[0][0] = ' ';
|
||||
return (argv[0][0] == ' ')?0:1;
|
||||
}" HAVE_WRITABLE_ARGV)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CMAKE_REQUIRED_FLAGS)
|
||||
|
||||
option(ENABLE_WEBSOCKETS "Set to ON to enable EXPERIMENTAL websockets" OFF)
|
||||
@@ -1525,11 +1578,7 @@ if(WIN32)
|
||||
list(APPEND CURL_LIBS "advapi32" "crypt32")
|
||||
endif()
|
||||
|
||||
if(NOT HAVE_MINGW_ORIGINAL)
|
||||
list(APPEND CURL_LIBS "bcrypt")
|
||||
else()
|
||||
set(HAVE_FTRUNCATE OFF)
|
||||
endif()
|
||||
list(APPEND CURL_LIBS "bcrypt")
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
@@ -1644,7 +1693,7 @@ macro(_add_if label)
|
||||
endmacro()
|
||||
|
||||
# NTLM support requires crypto function adaptions from various SSL libs
|
||||
# TODO alternative SSL libs tests for SSP1, GNUTLS, NSS
|
||||
# TODO alternative SSL libs tests for SSP1, GnuTLS, NSS
|
||||
if(NOT (CURL_DISABLE_NTLM) AND
|
||||
(USE_OPENSSL OR USE_MBEDTLS OR USE_DARWINSSL OR USE_WIN32_CRYPTO OR USE_GNUTLS))
|
||||
set(use_curl_ntlm_core ON)
|
||||
@@ -1673,14 +1722,13 @@ _add_if("SPNEGO" NOT CURL_DISABLE_NEGOTIATE_AUTH AND
|
||||
_add_if("Kerberos" NOT CURL_DISABLE_KERBEROS_AUTH AND
|
||||
(HAVE_GSSAPI OR USE_WINDOWS_SSPI))
|
||||
# NTLM support requires crypto function adaptions from various SSL libs
|
||||
# TODO alternative SSL libs tests for SSP1, GNUTLS, NSS
|
||||
# TODO alternative SSL libs tests for SSP1, GnuTLS, NSS
|
||||
_add_if("NTLM" NOT (CURL_DISABLE_NTLM) AND
|
||||
(use_curl_ntlm_core OR USE_WINDOWS_SSPI))
|
||||
# TODO missing option (autoconf: --enable-ntlm-wb)
|
||||
_add_if("NTLM_WB" NOT (CURL_DISABLE_NTLM) AND
|
||||
(use_curl_ntlm_core OR USE_WINDOWS_SSPI) AND
|
||||
NOT CURL_DISABLE_HTTP AND NTLM_WB_ENABLED)
|
||||
# TODO missing option (--enable-tls-srp), depends on GNUTLS_SRP/OPENSSL_SRP
|
||||
_add_if("TLS-SRP" USE_TLS_SRP)
|
||||
# TODO option --with-nghttp2 tests for nghttp2 lib and nghttp2/nghttp2.h header
|
||||
_add_if("HTTP2" USE_NGHTTP2)
|
||||
@@ -1707,7 +1755,6 @@ _add_if("FILE" NOT CURL_DISABLE_FILE)
|
||||
_add_if("TELNET" NOT CURL_DISABLE_TELNET)
|
||||
_add_if("LDAP" NOT CURL_DISABLE_LDAP)
|
||||
# CURL_DISABLE_LDAP implies CURL_DISABLE_LDAPS
|
||||
# TODO check HAVE_LDAP_SSL (in autoconf this is enabled with --enable-ldaps)
|
||||
_add_if("LDAPS" NOT CURL_DISABLE_LDAPS AND
|
||||
((USE_OPENLDAP AND SSL_ENABLED) OR
|
||||
(NOT USE_OPENLDAP AND HAVE_LDAP_SSL)))
|
||||
|
||||
@@ -159,7 +159,7 @@ typedef enum {
|
||||
CURLSSLBACKEND_NONE = 0,
|
||||
CURLSSLBACKEND_OPENSSL = 1,
|
||||
CURLSSLBACKEND_GNUTLS = 2,
|
||||
CURLSSLBACKEND_NSS = 3,
|
||||
CURLSSLBACKEND_NSS CURL_DEPRECATED(8.3.0, "") = 3,
|
||||
CURLSSLBACKEND_OBSOLETE4 = 4, /* Was QSOSSL. */
|
||||
CURLSSLBACKEND_GSKIT CURL_DEPRECATED(8.3.0, "") = 5,
|
||||
CURLSSLBACKEND_POLARSSL CURL_DEPRECATED(7.69.0, "") = 6,
|
||||
@@ -646,10 +646,10 @@ typedef enum {
|
||||
#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
|
||||
the obsolete stuff removed! */
|
||||
|
||||
/* Previously obsolete error code re-used in 7.38.0 */
|
||||
/* Previously obsolete error code reused in 7.38.0 */
|
||||
#define CURLE_OBSOLETE16 CURLE_HTTP2
|
||||
|
||||
/* Previously obsolete error codes re-used in 7.24.0 */
|
||||
/* Previously obsolete error codes reused in 7.24.0 */
|
||||
#define CURLE_OBSOLETE10 CURLE_FTP_ACCEPT_FAILED
|
||||
#define CURLE_OBSOLETE12 CURLE_FTP_ACCEPT_TIMEOUT
|
||||
|
||||
@@ -1358,7 +1358,7 @@ typedef enum {
|
||||
operation slower and is less friendly for the network. */
|
||||
CURLOPT(CURLOPT_FRESH_CONNECT, CURLOPTTYPE_LONG, 74),
|
||||
|
||||
/* Set to explicitly forbid the upcoming transfer's connection to be re-used
|
||||
/* Set to explicitly forbid the upcoming transfer's connection to be reused
|
||||
when done. Do not use this unless you're absolutely sure of this, as it
|
||||
makes the operation slower and is less friendly for the network. */
|
||||
CURLOPT(CURLOPT_FORBID_REUSE, CURLOPTTYPE_LONG, 75),
|
||||
@@ -1652,7 +1652,7 @@ typedef enum {
|
||||
CURLOPT(CURLOPT_SOCKOPTFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 148),
|
||||
CURLOPT(CURLOPT_SOCKOPTDATA, CURLOPTTYPE_CBPOINT, 149),
|
||||
|
||||
/* set to 0 to disable session ID re-use for this transfer, default is
|
||||
/* set to 0 to disable session ID reuse for this transfer, default is
|
||||
enabled (== 1) */
|
||||
CURLOPT(CURLOPT_SSL_SESSIONID_CACHE, CURLOPTTYPE_LONG, 150),
|
||||
|
||||
|
||||
@@ -32,12 +32,12 @@
|
||||
|
||||
/* This is the version number of the libcurl package from which this header
|
||||
file origins: */
|
||||
#define LIBCURL_VERSION "8.3.0"
|
||||
#define LIBCURL_VERSION "8.4.0"
|
||||
|
||||
/* The numeric version number is also available "in parts" by using these
|
||||
defines: */
|
||||
#define LIBCURL_VERSION_MAJOR 8
|
||||
#define LIBCURL_VERSION_MINOR 3
|
||||
#define LIBCURL_VERSION_MINOR 4
|
||||
#define LIBCURL_VERSION_PATCH 0
|
||||
|
||||
/* 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 0x080300
|
||||
#define LIBCURL_VERSION_NUM 0x080400
|
||||
|
||||
/*
|
||||
* This is the date and time when the full source package was created. The
|
||||
|
||||
@@ -426,6 +426,17 @@ CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle,
|
||||
CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle,
|
||||
curl_socket_t sockfd, void *sockp);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_get_handles()
|
||||
*
|
||||
* Desc: Returns an allocated array holding all handles currently added to
|
||||
* the multi handle. Marks the final entry with a NULL pointer. If
|
||||
* there is no easy handle added to the multi handle, this function
|
||||
* returns an array with the first entry as a NULL pointer.
|
||||
*
|
||||
* Returns: NULL on failure, otherwise a CURL **array pointer
|
||||
*/
|
||||
CURL_EXTERN CURL **curl_multi_get_handles(CURLM *multi_handle);
|
||||
|
||||
/*
|
||||
* Name: curl_push_callback
|
||||
|
||||
@@ -94,9 +94,9 @@ add_library(
|
||||
target_compile_definitions(curlu PUBLIC UNITTESTS CURL_STATICLIB)
|
||||
|
||||
if(ENABLE_CURLDEBUG)
|
||||
# We must compile memdebug.c separately to avoid memdebug.h redefinitions
|
||||
# being applied to memdebug.c itself.
|
||||
set_source_files_properties(memdebug.c PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON)
|
||||
# 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)
|
||||
endif()
|
||||
target_link_libraries(curlu PRIVATE ${CURL_LIBS})
|
||||
|
||||
@@ -123,19 +123,6 @@ else()
|
||||
unset(CMAKESONAME)
|
||||
endif()
|
||||
|
||||
if(NOT WIN32 AND NOT CMAKE_CROSSCOMPILING)
|
||||
# on not-Windows and not-crosscompiling, check for writable argv[]
|
||||
include(CheckCSourceRuns)
|
||||
check_c_source_runs("
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
argv[0][0] = ' ';
|
||||
return (argv[0][0] == ' ')?0:1;
|
||||
}"
|
||||
HAVE_WRITABLE_ARGV)
|
||||
endif()
|
||||
|
||||
## Library definition
|
||||
|
||||
# Add "_imp" as a suffix before the extension to avoid conflicting with
|
||||
@@ -160,18 +147,23 @@ if(NOT DEFINED SHARE_LIB_OBJECT)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
# Define CURL_STATICLIB always, to disable __declspec(dllexport) for 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.
|
||||
add_definitions("-DCURL_STATICLIB")
|
||||
endif()
|
||||
|
||||
if(SHARE_LIB_OBJECT)
|
||||
set(LIB_OBJECT "libcurl_object")
|
||||
add_library(${LIB_OBJECT} OBJECT ${HHEADERS} ${CSOURCES})
|
||||
target_link_libraries(${LIB_OBJECT} PRIVATE ${CURL_LIBS})
|
||||
set_target_properties(${LIB_OBJECT} PROPERTIES
|
||||
COMPILE_DEFINITIONS "BUILDING_LIBCURL"
|
||||
INTERFACE_COMPILE_DEFINITIONS "CURL_STATICLIB"
|
||||
POSITION_INDEPENDENT_CODE ON)
|
||||
if(HIDES_CURL_PRIVATE_SYMBOLS)
|
||||
set_target_properties(${LIB_OBJECT} PROPERTIES
|
||||
COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS"
|
||||
COMPILE_FLAGS "${CURL_CFLAG_SYMBOLS_HIDE}")
|
||||
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()
|
||||
if(CURL_HAS_LTO)
|
||||
set_target_properties(${LIB_OBJECT} PROPERTIES
|
||||
@@ -198,12 +190,10 @@ if(BUILD_STATIC_LIBS)
|
||||
set_target_properties(${LIB_STATIC} PROPERTIES
|
||||
PREFIX "" OUTPUT_NAME "${LIBCURL_OUTPUT_NAME}"
|
||||
SUFFIX "${STATIC_LIB_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}"
|
||||
COMPILE_DEFINITIONS "BUILDING_LIBCURL"
|
||||
INTERFACE_COMPILE_DEFINITIONS "CURL_STATICLIB")
|
||||
if(HIDES_CURL_PRIVATE_SYMBOLS)
|
||||
set_target_properties(${LIB_STATIC} PROPERTIES
|
||||
COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS"
|
||||
COMPILE_FLAGS "${CURL_CFLAG_SYMBOLS_HIDE}")
|
||||
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()
|
||||
if(CURL_HAS_LTO)
|
||||
set_target_properties(${LIB_STATIC} PROPERTIES
|
||||
@@ -225,19 +215,20 @@ if(BUILD_SHARED_LIBS)
|
||||
add_library(${LIB_SHARED} SHARED ${LIB_SOURCE})
|
||||
add_library(${PROJECT_NAME}::${LIB_SHARED} ALIAS ${LIB_SHARED})
|
||||
if(WIN32)
|
||||
set_property(TARGET ${LIB_SHARED} APPEND PROPERTY SOURCES libcurl.rc ${CURL_SOURCE_DIR}/libcurl.def)
|
||||
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")
|
||||
endif()
|
||||
endif()
|
||||
target_link_libraries(${LIB_SHARED} PRIVATE ${CURL_LIBS})
|
||||
# Remove the "lib" prefix since the library is already named "libcurl".
|
||||
set_target_properties(${LIB_SHARED} PROPERTIES
|
||||
PREFIX "" OUTPUT_NAME "${LIBCURL_OUTPUT_NAME}"
|
||||
IMPORT_PREFIX "" IMPORT_SUFFIX "${IMPORT_LIB_SUFFIX}${CMAKE_IMPORT_LIBRARY_SUFFIX}"
|
||||
COMPILE_DEFINITIONS "BUILDING_LIBCURL"
|
||||
POSITION_INDEPENDENT_CODE ON)
|
||||
if(HIDES_CURL_PRIVATE_SYMBOLS)
|
||||
set_target_properties(${LIB_SHARED} PROPERTIES
|
||||
COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS"
|
||||
COMPILE_FLAGS "${CURL_CFLAG_SYMBOLS_HIDE}")
|
||||
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()
|
||||
if(CURL_HAS_LTO)
|
||||
set_target_properties(${LIB_SHARED} PROPERTIES
|
||||
|
||||
@@ -162,12 +162,12 @@ LIB_CFILES = \
|
||||
http.c \
|
||||
http1.c \
|
||||
http2.c \
|
||||
http_aws_sigv4.c \
|
||||
http_chunks.c \
|
||||
http_digest.c \
|
||||
http_negotiate.c \
|
||||
http_ntlm.c \
|
||||
http_proxy.c \
|
||||
http_aws_sigv4.c \
|
||||
idn.c \
|
||||
if2ip.c \
|
||||
imap.c \
|
||||
@@ -289,9 +289,9 @@ LIB_HFILES = \
|
||||
fileinfo.h \
|
||||
fopen.h \
|
||||
formdata.h \
|
||||
functypes.h \
|
||||
ftp.h \
|
||||
ftplistparser.h \
|
||||
functypes.h \
|
||||
getinfo.h \
|
||||
gopher.h \
|
||||
hash.h \
|
||||
@@ -301,12 +301,12 @@ LIB_HFILES = \
|
||||
http.h \
|
||||
http1.h \
|
||||
http2.h \
|
||||
http_aws_sigv4.h \
|
||||
http_chunks.h \
|
||||
http_digest.h \
|
||||
http_negotiate.h \
|
||||
http_ntlm.h \
|
||||
http_proxy.h \
|
||||
http_aws_sigv4.h \
|
||||
idn.h \
|
||||
if2ip.h \
|
||||
imap.h \
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
!defined(CURL_DISABLE_SMTP) || \
|
||||
!defined(CURL_DISABLE_POP3) || \
|
||||
!defined(CURL_DISABLE_IMAP) || \
|
||||
!defined(CURL_DISABLE_DOH) || defined(USE_SSL)
|
||||
!defined(CURL_DISABLE_DOH) || defined(USE_SSL) || defined(BUILDING_CURL)
|
||||
#include "curl/curl.h"
|
||||
#include "warnless.h"
|
||||
#include "curl_base64.h"
|
||||
|
||||
@@ -144,21 +144,6 @@ static size_t chunk_skip(struct buf_chunk *chunk, size_t amount)
|
||||
return n;
|
||||
}
|
||||
|
||||
static void chunk_shift(struct buf_chunk *chunk)
|
||||
{
|
||||
if(chunk->r_offset) {
|
||||
if(!chunk_is_empty(chunk)) {
|
||||
size_t n = chunk->w_offset - chunk->r_offset;
|
||||
memmove(chunk->x.data, chunk->x.data + chunk->r_offset, n);
|
||||
chunk->w_offset -= chunk->r_offset;
|
||||
chunk->r_offset = 0;
|
||||
}
|
||||
else {
|
||||
chunk->r_offset = chunk->w_offset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void chunk_list_free(struct buf_chunk **anchor)
|
||||
{
|
||||
struct buf_chunk *chunk;
|
||||
@@ -504,13 +489,6 @@ void Curl_bufq_skip(struct bufq *q, size_t amount)
|
||||
}
|
||||
}
|
||||
|
||||
void Curl_bufq_skip_and_shift(struct bufq *q, size_t amount)
|
||||
{
|
||||
Curl_bufq_skip(q, amount);
|
||||
if(q->tail)
|
||||
chunk_shift(q->tail);
|
||||
}
|
||||
|
||||
ssize_t Curl_bufq_pass(struct bufq *q, Curl_bufq_writer *writer,
|
||||
void *writer_ctx, CURLcode *err)
|
||||
{
|
||||
|
||||
@@ -209,12 +209,6 @@ bool Curl_bufq_peek_at(struct bufq *q, size_t offset,
|
||||
*/
|
||||
void Curl_bufq_skip(struct bufq *q, size_t amount);
|
||||
|
||||
/**
|
||||
* Same as `skip` but shift tail data to the start afterwards,
|
||||
* so that further writes will find room in tail.
|
||||
*/
|
||||
void Curl_bufq_skip_and_shift(struct bufq *q, size_t amount);
|
||||
|
||||
typedef ssize_t Curl_bufq_writer(void *writer_ctx,
|
||||
const unsigned char *buf, size_t len,
|
||||
CURLcode *err);
|
||||
|
||||
@@ -174,8 +174,6 @@ static int hyper_each_header(void *userdata,
|
||||
|
||||
if(!data->state.hconnect || !data->set.suppress_connect_headers) {
|
||||
writetype = CLIENTWRITE_HEADER;
|
||||
if(data->set.include_header)
|
||||
writetype |= CLIENTWRITE_BODY;
|
||||
if(data->state.hconnect)
|
||||
writetype |= CLIENTWRITE_CONNECT;
|
||||
if(data->req.httpcode/100 == 1)
|
||||
@@ -248,11 +246,7 @@ static int hyper_body_chunk(void *userdata, const hyper_buf *chunk)
|
||||
if(0 == len)
|
||||
return HYPER_ITER_CONTINUE;
|
||||
Curl_debug(data, CURLINFO_DATA_IN, buf, len);
|
||||
if(!data->set.http_ce_skip && k->writer_stack)
|
||||
/* content-encoded data */
|
||||
result = Curl_unencode_write(data, k->writer_stack, buf, len);
|
||||
else
|
||||
result = Curl_client_write(data, CLIENTWRITE_BODY, buf, len);
|
||||
result = Curl_client_write(data, CLIENTWRITE_BODY, buf, len);
|
||||
|
||||
if(result) {
|
||||
data->state.hresult = result;
|
||||
@@ -260,7 +254,11 @@ static int hyper_body_chunk(void *userdata, const hyper_buf *chunk)
|
||||
}
|
||||
|
||||
data->req.bytecount += len;
|
||||
Curl_pgrsSetDownloadCounter(data, data->req.bytecount);
|
||||
result = Curl_pgrsSetDownloadCounter(data, data->req.bytecount);
|
||||
if(result) {
|
||||
data->state.hresult = result;
|
||||
return HYPER_ITER_BREAK;
|
||||
}
|
||||
return HYPER_ITER_CONTINUE;
|
||||
}
|
||||
|
||||
@@ -314,8 +312,6 @@ static CURLcode status_line(struct Curl_easy *data,
|
||||
|
||||
if(!data->state.hconnect || !data->set.suppress_connect_headers) {
|
||||
writetype = CLIENTWRITE_HEADER|CLIENTWRITE_STATUS;
|
||||
if(data->set.include_header)
|
||||
writetype |= CLIENTWRITE_BODY;
|
||||
result = Curl_client_write(data, writetype,
|
||||
Curl_dyn_ptr(&data->state.headerb), len);
|
||||
if(result)
|
||||
|
||||
+107
-182
@@ -34,6 +34,7 @@
|
||||
#include "dynbuf.h"
|
||||
#include "sendf.h"
|
||||
#include "http.h"
|
||||
#include "http1.h"
|
||||
#include "http_proxy.h"
|
||||
#include "url.h"
|
||||
#include "select.h"
|
||||
@@ -64,13 +65,10 @@ typedef enum {
|
||||
|
||||
/* struct for HTTP CONNECT tunneling */
|
||||
struct h1_tunnel_state {
|
||||
int sockindex;
|
||||
const char *hostname;
|
||||
int remote_port;
|
||||
struct HTTP CONNECT;
|
||||
struct dynbuf rcvbuf;
|
||||
struct dynbuf req;
|
||||
size_t nsend;
|
||||
struct dynbuf request_data;
|
||||
size_t nsent;
|
||||
size_t headerlines;
|
||||
enum keeponval {
|
||||
KEEPON_DONE,
|
||||
@@ -94,46 +92,31 @@ static bool tunnel_is_failed(struct h1_tunnel_state *ts)
|
||||
return ts && (ts->tunnel_state == H1_TUNNEL_FAILED);
|
||||
}
|
||||
|
||||
static CURLcode tunnel_reinit(struct h1_tunnel_state *ts,
|
||||
struct connectdata *conn,
|
||||
struct Curl_easy *data)
|
||||
static CURLcode tunnel_reinit(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
struct h1_tunnel_state *ts)
|
||||
{
|
||||
(void)data;
|
||||
(void)cf;
|
||||
DEBUGASSERT(ts);
|
||||
Curl_dyn_reset(&ts->rcvbuf);
|
||||
Curl_dyn_reset(&ts->req);
|
||||
Curl_dyn_reset(&ts->request_data);
|
||||
ts->tunnel_state = H1_TUNNEL_INIT;
|
||||
ts->keepon = KEEPON_CONNECT;
|
||||
ts->cl = 0;
|
||||
ts->close_connection = FALSE;
|
||||
|
||||
if(conn->bits.conn_to_host)
|
||||
ts->hostname = conn->conn_to_host.name;
|
||||
else if(ts->sockindex == SECONDARYSOCKET)
|
||||
ts->hostname = conn->secondaryhostname;
|
||||
else
|
||||
ts->hostname = conn->host.name;
|
||||
|
||||
if(ts->sockindex == SECONDARYSOCKET)
|
||||
ts->remote_port = conn->secondary_port;
|
||||
else if(conn->bits.conn_to_port)
|
||||
ts->remote_port = conn->conn_to_port;
|
||||
else
|
||||
ts->remote_port = conn->remote_port;
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static CURLcode tunnel_init(struct h1_tunnel_state **pts,
|
||||
static CURLcode tunnel_init(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
int sockindex)
|
||||
struct h1_tunnel_state **pts)
|
||||
{
|
||||
struct h1_tunnel_state *ts;
|
||||
CURLcode result;
|
||||
|
||||
if(conn->handler->flags & PROTOPT_NOTCPPROXY) {
|
||||
failf(data, "%s cannot be done over CONNECT", conn->handler->scheme);
|
||||
if(cf->conn->handler->flags & PROTOPT_NOTCPPROXY) {
|
||||
failf(data, "%s cannot be done over CONNECT", cf->conn->handler->scheme);
|
||||
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||
}
|
||||
|
||||
@@ -146,15 +129,14 @@ static CURLcode tunnel_init(struct h1_tunnel_state **pts,
|
||||
if(!ts)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
ts->sockindex = sockindex;
|
||||
infof(data, "allocate connect buffer");
|
||||
|
||||
Curl_dyn_init(&ts->rcvbuf, DYN_PROXY_CONNECT_HEADERS);
|
||||
Curl_dyn_init(&ts->req, DYN_HTTP_REQUEST);
|
||||
Curl_dyn_init(&ts->request_data, DYN_HTTP_REQUEST);
|
||||
|
||||
*pts = ts;
|
||||
connkeep(conn, "HTTP proxy CONNECT");
|
||||
return tunnel_reinit(ts, conn, data);
|
||||
connkeep(cf->conn, "HTTP proxy CONNECT");
|
||||
return tunnel_reinit(cf, data, ts);
|
||||
}
|
||||
|
||||
static void h1_tunnel_go_state(struct Curl_cfilter *cf,
|
||||
@@ -176,7 +158,7 @@ static void h1_tunnel_go_state(struct Curl_cfilter *cf,
|
||||
switch(new_state) {
|
||||
case H1_TUNNEL_INIT:
|
||||
CURL_TRC_CF(data, cf, "new tunnel state 'init'");
|
||||
tunnel_reinit(ts, cf->conn, data);
|
||||
tunnel_reinit(cf, data, ts);
|
||||
break;
|
||||
|
||||
case H1_TUNNEL_CONNECT:
|
||||
@@ -207,7 +189,7 @@ static void h1_tunnel_go_state(struct Curl_cfilter *cf,
|
||||
CURL_TRC_CF(data, cf, "new tunnel state 'failed'");
|
||||
ts->tunnel_state = new_state;
|
||||
Curl_dyn_reset(&ts->rcvbuf);
|
||||
Curl_dyn_reset(&ts->req);
|
||||
Curl_dyn_reset(&ts->request_data);
|
||||
/* restore the protocol pointer */
|
||||
data->info.httpcode = 0; /* clear it as it might've been used for the
|
||||
proxy */
|
||||
@@ -229,171 +211,80 @@ static void tunnel_free(struct Curl_cfilter *cf,
|
||||
if(ts) {
|
||||
h1_tunnel_go_state(cf, ts, H1_TUNNEL_FAILED, data);
|
||||
Curl_dyn_free(&ts->rcvbuf);
|
||||
Curl_dyn_free(&ts->req);
|
||||
Curl_dyn_free(&ts->request_data);
|
||||
free(ts);
|
||||
cf->ctx = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static CURLcode CONNECT_host(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
const char *hostname,
|
||||
int remote_port,
|
||||
char **connecthostp,
|
||||
char **hostp)
|
||||
{
|
||||
char *hostheader; /* for CONNECT */
|
||||
char *host = NULL; /* Host: */
|
||||
bool ipv6_ip = conn->bits.ipv6_ip;
|
||||
|
||||
/* the hostname may be different */
|
||||
if(hostname != conn->host.name)
|
||||
ipv6_ip = (strchr(hostname, ':') != NULL);
|
||||
hostheader = /* host:port with IPv6 support */
|
||||
aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"",
|
||||
remote_port);
|
||||
if(!hostheader)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
if(!Curl_checkProxyheaders(data, conn, STRCONST("Host"))) {
|
||||
host = aprintf("Host: %s\r\n", hostheader);
|
||||
if(!host) {
|
||||
free(hostheader);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
*connecthostp = hostheader;
|
||||
*hostp = host;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
#ifndef USE_HYPER
|
||||
static CURLcode start_CONNECT(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
struct h1_tunnel_state *ts)
|
||||
{
|
||||
struct connectdata *conn = cf->conn;
|
||||
char *hostheader = NULL;
|
||||
char *host = NULL;
|
||||
const char *httpv;
|
||||
struct httpreq *req = NULL;
|
||||
int http_minor;
|
||||
CURLcode result;
|
||||
|
||||
infof(data, "Establish HTTP proxy tunnel to %s:%d",
|
||||
ts->hostname, ts->remote_port);
|
||||
|
||||
/* This only happens if we've looped here due to authentication
|
||||
reasons, and we don't really use the newly cloned URL here
|
||||
then. Just free() it. */
|
||||
Curl_safefree(data->req.newurl);
|
||||
|
||||
result = CONNECT_host(data, conn,
|
||||
ts->hostname, ts->remote_port,
|
||||
&hostheader, &host);
|
||||
result = Curl_http_proxy_create_CONNECT(&req, cf, data, 1);
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
/* Setup the proxy-authorization header, if any */
|
||||
result = Curl_http_output_auth(data, conn, "CONNECT", HTTPREQ_GET,
|
||||
hostheader, TRUE);
|
||||
if(result)
|
||||
goto out;
|
||||
infof(data, "Establish HTTP proxy tunnel to %s", req->authority);
|
||||
|
||||
httpv = (conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) ? "1.0" : "1.1";
|
||||
|
||||
result =
|
||||
Curl_dyn_addf(&ts->req,
|
||||
"CONNECT %s HTTP/%s\r\n"
|
||||
"%s" /* Host: */
|
||||
"%s", /* Proxy-Authorization */
|
||||
hostheader,
|
||||
httpv,
|
||||
host?host:"",
|
||||
data->state.aptr.proxyuserpwd?
|
||||
data->state.aptr.proxyuserpwd:"");
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
if(!Curl_checkProxyheaders(data, conn, STRCONST("User-Agent"))
|
||||
&& data->set.str[STRING_USERAGENT])
|
||||
result = Curl_dyn_addf(&ts->req, "User-Agent: %s\r\n",
|
||||
data->set.str[STRING_USERAGENT]);
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
if(!Curl_checkProxyheaders(data, conn, STRCONST("Proxy-Connection")))
|
||||
result = Curl_dyn_addn(&ts->req,
|
||||
STRCONST("Proxy-Connection: Keep-Alive\r\n"));
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
result = Curl_add_custom_headers(data, TRUE, &ts->req);
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
/* CRLF terminate the request */
|
||||
result = Curl_dyn_addn(&ts->req, STRCONST("\r\n"));
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
/* Send the connect request to the proxy */
|
||||
result = Curl_buffer_send(&ts->req, data, &ts->CONNECT,
|
||||
&data->info.request_size, 0,
|
||||
ts->sockindex);
|
||||
Curl_dyn_reset(&ts->request_data);
|
||||
ts->nsent = 0;
|
||||
ts->headerlines = 0;
|
||||
http_minor = (cf->conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) ? 0 : 1;
|
||||
|
||||
result = Curl_h1_req_write_head(req, http_minor, &ts->request_data);
|
||||
|
||||
out:
|
||||
if(result)
|
||||
failf(data, "Failed sending CONNECT to proxy");
|
||||
free(host);
|
||||
free(hostheader);
|
||||
if(req)
|
||||
Curl_http_req_free(req);
|
||||
return result;
|
||||
}
|
||||
|
||||
static CURLcode send_CONNECT(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
static CURLcode send_CONNECT(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
struct h1_tunnel_state *ts,
|
||||
bool *done)
|
||||
{
|
||||
struct SingleRequest *k = &data->req;
|
||||
struct HTTP *http = &ts->CONNECT;
|
||||
char *buf = Curl_dyn_ptr(&ts->request_data);
|
||||
size_t request_len = Curl_dyn_len(&ts->request_data);
|
||||
size_t blen = request_len;
|
||||
CURLcode result = CURLE_OK;
|
||||
ssize_t nwritten;
|
||||
|
||||
if(http->sending != HTTPSEND_REQUEST)
|
||||
if(blen <= ts->nsent)
|
||||
goto out; /* we are done */
|
||||
|
||||
blen -= ts->nsent;
|
||||
buf += ts->nsent;
|
||||
|
||||
nwritten = cf->next->cft->do_send(cf->next, data, buf, blen, &result);
|
||||
if(nwritten < 0) {
|
||||
if(result == CURLE_AGAIN) {
|
||||
result = CURLE_OK;
|
||||
}
|
||||
goto out;
|
||||
|
||||
if(!ts->nsend) {
|
||||
size_t fillcount;
|
||||
k->upload_fromhere = data->state.ulbuf;
|
||||
result = Curl_fillreadbuffer(data, data->set.upload_buffer_size,
|
||||
&fillcount);
|
||||
if(result)
|
||||
goto out;
|
||||
ts->nsend = fillcount;
|
||||
}
|
||||
if(ts->nsend) {
|
||||
ssize_t bytes_written;
|
||||
/* write to socket (send away data) */
|
||||
result = Curl_write(data,
|
||||
conn->writesockfd, /* socket to send to */
|
||||
k->upload_fromhere, /* buffer pointer */
|
||||
ts->nsend, /* buffer size */
|
||||
&bytes_written); /* actually sent */
|
||||
if(result)
|
||||
goto out;
|
||||
/* send to debug callback! */
|
||||
Curl_debug(data, CURLINFO_HEADER_OUT,
|
||||
k->upload_fromhere, bytes_written);
|
||||
|
||||
ts->nsend -= bytes_written;
|
||||
k->upload_fromhere += bytes_written;
|
||||
}
|
||||
if(!ts->nsend)
|
||||
http->sending = HTTPSEND_NADA;
|
||||
DEBUGASSERT(blen >= (size_t)nwritten);
|
||||
ts->nsent += (size_t)nwritten;
|
||||
Curl_debug(data, CURLINFO_HEADER_OUT, buf, (size_t)nwritten);
|
||||
|
||||
out:
|
||||
if(result)
|
||||
failf(data, "Failed sending CONNECT to proxy");
|
||||
*done = (http->sending != HTTPSEND_REQUEST);
|
||||
*done = (!result && (ts->nsent >= request_len));
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -491,7 +382,7 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
|
||||
error = SELECT_OK;
|
||||
*done = FALSE;
|
||||
|
||||
if(!Curl_conn_data_pending(data, ts->sockindex))
|
||||
if(!Curl_conn_data_pending(data, cf->sockindex))
|
||||
return CURLE_OK;
|
||||
|
||||
while(ts->keepon) {
|
||||
@@ -579,7 +470,6 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
|
||||
if(!data->set.suppress_connect_headers) {
|
||||
/* send the header to the callback */
|
||||
int writetype = CLIENTWRITE_HEADER | CLIENTWRITE_CONNECT |
|
||||
(data->set.include_header ? CLIENTWRITE_BODY : 0) |
|
||||
(ts->headerlines == 1 ? CLIENTWRITE_STATUS : 0);
|
||||
|
||||
result = Curl_client_write(data, writetype, linep, perline);
|
||||
@@ -670,6 +560,41 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
|
||||
}
|
||||
|
||||
#else /* USE_HYPER */
|
||||
|
||||
static CURLcode CONNECT_host(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
char **pauthority,
|
||||
char **phost_header)
|
||||
{
|
||||
const char *hostname;
|
||||
int port;
|
||||
bool ipv6_ip;
|
||||
CURLcode result;
|
||||
char *authority; /* for CONNECT, the destination host + port */
|
||||
char *host_header = NULL; /* Host: authority */
|
||||
|
||||
result = Curl_http_proxy_get_destination(cf, &hostname, &port, &ipv6_ip);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
authority = aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"",
|
||||
port);
|
||||
if(!authority)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
/* If user is not overriding the Host header later */
|
||||
if(!Curl_checkProxyheaders(data, cf->conn, STRCONST("Host"))) {
|
||||
host_header = aprintf("Host: %s\r\n", authority);
|
||||
if(!host_header) {
|
||||
free(authority);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
*pauthority = authority;
|
||||
*phost_header = host_header;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/* The Hyper version of CONNECT */
|
||||
static CURLcode start_CONNECT(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
@@ -686,9 +611,10 @@ static CURLcode start_CONNECT(struct Curl_cfilter *cf,
|
||||
hyper_task *task = NULL; /* for the handshake */
|
||||
hyper_clientconn *client = NULL;
|
||||
hyper_task *sendtask = NULL; /* for the send */
|
||||
char *hostheader = NULL; /* for CONNECT */
|
||||
char *host = NULL; /* Host: */
|
||||
char *authority = NULL; /* for CONNECT */
|
||||
char *host_header = NULL; /* Host: */
|
||||
CURLcode result = CURLE_OUT_OF_MEMORY;
|
||||
(void)ts;
|
||||
|
||||
io = hyper_io_new();
|
||||
if(!io) {
|
||||
@@ -766,27 +692,25 @@ static CURLcode start_CONNECT(struct Curl_cfilter *cf,
|
||||
goto error;
|
||||
}
|
||||
|
||||
infof(data, "Establish HTTP proxy tunnel to %s:%d",
|
||||
ts->hostname, ts->remote_port);
|
||||
|
||||
/* This only happens if we've looped here due to authentication
|
||||
reasons, and we don't really use the newly cloned URL here
|
||||
then. Just free() it. */
|
||||
Curl_safefree(data->req.newurl);
|
||||
|
||||
result = CONNECT_host(data, conn, ts->hostname, ts->remote_port,
|
||||
&hostheader, &host);
|
||||
result = CONNECT_host(cf, data, &authority, &host_header);
|
||||
if(result)
|
||||
goto error;
|
||||
|
||||
if(hyper_request_set_uri(req, (uint8_t *)hostheader,
|
||||
strlen(hostheader))) {
|
||||
infof(data, "Establish HTTP proxy tunnel to %s", authority);
|
||||
|
||||
if(hyper_request_set_uri(req, (uint8_t *)authority,
|
||||
strlen(authority))) {
|
||||
failf(data, "error setting path");
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto error;
|
||||
}
|
||||
if(data->set.verbose) {
|
||||
char *se = aprintf("CONNECT %s HTTP/1.1\r\n", hostheader);
|
||||
char *se = aprintf("CONNECT %s HTTP/1.1\r\n", authority);
|
||||
if(!se) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto error;
|
||||
@@ -796,10 +720,10 @@ static CURLcode start_CONNECT(struct Curl_cfilter *cf,
|
||||
}
|
||||
/* Setup the proxy-authorization header, if any */
|
||||
result = Curl_http_output_auth(data, conn, "CONNECT", HTTPREQ_GET,
|
||||
hostheader, TRUE);
|
||||
authority, TRUE);
|
||||
if(result)
|
||||
goto error;
|
||||
Curl_safefree(hostheader);
|
||||
Curl_safefree(authority);
|
||||
|
||||
/* default is 1.1 */
|
||||
if((conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) &&
|
||||
@@ -816,11 +740,11 @@ static CURLcode start_CONNECT(struct Curl_cfilter *cf,
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto error;
|
||||
}
|
||||
if(host) {
|
||||
result = Curl_hyper_header(data, headers, host);
|
||||
if(host_header) {
|
||||
result = Curl_hyper_header(data, headers, host_header);
|
||||
if(result)
|
||||
goto error;
|
||||
Curl_safefree(host);
|
||||
Curl_safefree(host_header);
|
||||
}
|
||||
|
||||
if(data->state.aptr.proxyuserpwd) {
|
||||
@@ -874,8 +798,8 @@ static CURLcode start_CONNECT(struct Curl_cfilter *cf,
|
||||
client = NULL;
|
||||
|
||||
error:
|
||||
free(host);
|
||||
free(hostheader);
|
||||
free(host_header);
|
||||
free(authority);
|
||||
if(io)
|
||||
hyper_io_free(io);
|
||||
if(options)
|
||||
@@ -890,12 +814,13 @@ error:
|
||||
return result;
|
||||
}
|
||||
|
||||
static CURLcode send_CONNECT(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
static CURLcode send_CONNECT(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
struct h1_tunnel_state *ts,
|
||||
bool *done)
|
||||
{
|
||||
struct hyptransfer *h = &data->hyp;
|
||||
struct connectdata *conn = cf->conn;
|
||||
hyper_task *task = NULL;
|
||||
hyper_error *hypererr = NULL;
|
||||
CURLcode result = CURLE_OK;
|
||||
@@ -995,7 +920,7 @@ static CURLcode H1_CONNECT(struct Curl_cfilter *cf,
|
||||
case H1_TUNNEL_CONNECT:
|
||||
/* see that the request is completely sent */
|
||||
CURL_TRC_CF(data, cf, "CONNECT send");
|
||||
result = send_CONNECT(data, cf->conn, ts, &done);
|
||||
result = send_CONNECT(cf, data, ts, &done);
|
||||
if(result || !done)
|
||||
goto out;
|
||||
h1_tunnel_go_state(cf, ts, H1_TUNNEL_RECEIVE, data);
|
||||
@@ -1090,7 +1015,7 @@ static CURLcode cf_h1_proxy_connect(struct Curl_cfilter *cf,
|
||||
|
||||
*done = FALSE;
|
||||
if(!ts) {
|
||||
result = tunnel_init(&ts, data, cf->conn, cf->sockindex);
|
||||
result = tunnel_init(cf, data, &ts);
|
||||
if(result)
|
||||
return result;
|
||||
cf->ctx = ts;
|
||||
|
||||
@@ -84,7 +84,8 @@ static CURLcode tunnel_stream_init(struct Curl_cfilter *cf,
|
||||
{
|
||||
const char *hostname;
|
||||
int port;
|
||||
bool ipv6_ip = cf->conn->bits.ipv6_ip;
|
||||
bool ipv6_ip;
|
||||
CURLcode result;
|
||||
|
||||
ts->state = H2_TUNNEL_INIT;
|
||||
ts->stream_id = -1;
|
||||
@@ -92,22 +93,9 @@ static CURLcode tunnel_stream_init(struct Curl_cfilter *cf,
|
||||
BUFQ_OPT_SOFT_LIMIT);
|
||||
Curl_bufq_init(&ts->sendbuf, PROXY_H2_CHUNK_SIZE, H2_TUNNEL_SEND_CHUNKS);
|
||||
|
||||
if(cf->conn->bits.conn_to_host)
|
||||
hostname = cf->conn->conn_to_host.name;
|
||||
else if(cf->sockindex == SECONDARYSOCKET)
|
||||
hostname = cf->conn->secondaryhostname;
|
||||
else
|
||||
hostname = cf->conn->host.name;
|
||||
|
||||
if(cf->sockindex == SECONDARYSOCKET)
|
||||
port = cf->conn->secondary_port;
|
||||
else if(cf->conn->bits.conn_to_port)
|
||||
port = cf->conn->conn_to_port;
|
||||
else
|
||||
port = cf->conn->remote_port;
|
||||
|
||||
if(hostname != cf->conn->host.name)
|
||||
ipv6_ip = (strchr(hostname, ':') != NULL);
|
||||
result = Curl_http_proxy_get_destination(cf, &hostname, &port, &ipv6_ip);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
ts->authority = /* host:port with IPv6 support */
|
||||
aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"", port);
|
||||
@@ -233,7 +221,7 @@ static void drain_tunnel(struct Curl_cfilter *cf,
|
||||
bits = CURL_CSELECT_IN;
|
||||
if(!tunnel->closed && !tunnel->reset && tunnel->upload_blocked_len)
|
||||
bits |= CURL_CSELECT_OUT;
|
||||
if(data->state.dselect_bits != bits || 1) {
|
||||
if(data->state.dselect_bits != bits) {
|
||||
CURL_TRC_CF(data, cf, "[%d] DRAIN dselect_bits=%x",
|
||||
tunnel->stream_id, bits);
|
||||
data->state.dselect_bits = bits;
|
||||
@@ -309,8 +297,9 @@ static int proxy_h2_on_frame_recv(nghttp2_session *session,
|
||||
const nghttp2_frame *frame,
|
||||
void *userp);
|
||||
#ifndef CURL_DISABLE_VERBOSE_STRINGS
|
||||
static int on_frame_send(nghttp2_session *session, const nghttp2_frame *frame,
|
||||
void *userp);
|
||||
static int proxy_h2_on_frame_send(nghttp2_session *session,
|
||||
const nghttp2_frame *frame,
|
||||
void *userp);
|
||||
#endif
|
||||
static int proxy_h2_on_stream_close(nghttp2_session *session,
|
||||
int32_t stream_id,
|
||||
@@ -355,7 +344,8 @@ static CURLcode cf_h2_proxy_ctx_init(struct Curl_cfilter *cf,
|
||||
nghttp2_session_callbacks_set_on_frame_recv_callback(
|
||||
cbs, proxy_h2_on_frame_recv);
|
||||
#ifndef CURL_DISABLE_VERBOSE_STRINGS
|
||||
nghttp2_session_callbacks_set_on_frame_send_callback(cbs, on_frame_send);
|
||||
nghttp2_session_callbacks_set_on_frame_send_callback(cbs,
|
||||
proxy_h2_on_frame_send);
|
||||
#endif
|
||||
nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
|
||||
cbs, tunnel_recv_callback);
|
||||
@@ -575,7 +565,8 @@ static ssize_t on_session_send(nghttp2_session *h2,
|
||||
}
|
||||
|
||||
#ifndef CURL_DISABLE_VERBOSE_STRINGS
|
||||
static int fr_print(const nghttp2_frame *frame, char *buffer, size_t blen)
|
||||
static int proxy_h2_fr_print(const nghttp2_frame *frame,
|
||||
char *buffer, size_t blen)
|
||||
{
|
||||
switch(frame->hd.type) {
|
||||
case NGHTTP2_DATA: {
|
||||
@@ -646,8 +637,9 @@ static int fr_print(const nghttp2_frame *frame, char *buffer, size_t blen)
|
||||
}
|
||||
}
|
||||
|
||||
static int on_frame_send(nghttp2_session *session, const nghttp2_frame *frame,
|
||||
void *userp)
|
||||
static int proxy_h2_on_frame_send(nghttp2_session *session,
|
||||
const nghttp2_frame *frame,
|
||||
void *userp)
|
||||
{
|
||||
struct Curl_cfilter *cf = userp;
|
||||
struct Curl_easy *data = CF_DATA_CURRENT(cf);
|
||||
@@ -657,7 +649,7 @@ static int on_frame_send(nghttp2_session *session, const nghttp2_frame *frame,
|
||||
if(data && Curl_trc_cf_is_verbose(cf, data)) {
|
||||
char buffer[256];
|
||||
int len;
|
||||
len = fr_print(frame, buffer, sizeof(buffer)-1);
|
||||
len = proxy_h2_fr_print(frame, buffer, sizeof(buffer)-1);
|
||||
buffer[len] = 0;
|
||||
CURL_TRC_CF(data, cf, "[%d] -> %s", frame->hd.stream_id, buffer);
|
||||
}
|
||||
@@ -680,7 +672,7 @@ static int proxy_h2_on_frame_recv(nghttp2_session *session,
|
||||
if(Curl_trc_cf_is_verbose(cf, data)) {
|
||||
char buffer[256];
|
||||
int len;
|
||||
len = fr_print(frame, buffer, sizeof(buffer)-1);
|
||||
len = proxy_h2_fr_print(frame, buffer, sizeof(buffer)-1);
|
||||
buffer[len] = 0;
|
||||
CURL_TRC_CF(data, cf, "[%d] <- %s",frame->hd.stream_id, buffer);
|
||||
}
|
||||
@@ -980,38 +972,11 @@ static CURLcode submit_CONNECT(struct Curl_cfilter *cf,
|
||||
CURLcode result;
|
||||
struct httpreq *req = NULL;
|
||||
|
||||
infof(data, "Establish HTTP/2 proxy tunnel to %s", ts->authority);
|
||||
|
||||
result = Curl_http_req_make(&req, "CONNECT", sizeof("CONNECT")-1,
|
||||
NULL, 0, ts->authority, strlen(ts->authority),
|
||||
NULL, 0);
|
||||
result = Curl_http_proxy_create_CONNECT(&req, cf, data, 2);
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
/* Setup the proxy-authorization header, if any */
|
||||
result = Curl_http_output_auth(data, cf->conn, req->method, HTTPREQ_GET,
|
||||
req->authority, TRUE);
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
if(data->state.aptr.proxyuserpwd) {
|
||||
result = Curl_dynhds_h1_cadd_line(&req->headers,
|
||||
data->state.aptr.proxyuserpwd);
|
||||
if(result)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(!Curl_checkProxyheaders(data, cf->conn, STRCONST("User-Agent"))
|
||||
&& data->set.str[STRING_USERAGENT]) {
|
||||
result = Curl_dynhds_cadd(&req->headers, "User-Agent",
|
||||
data->set.str[STRING_USERAGENT]);
|
||||
if(result)
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = Curl_dynhds_add_custom(data, TRUE, &req->headers);
|
||||
if(result)
|
||||
goto out;
|
||||
infof(data, "Establish HTTP/2 proxy tunnel to %s", req->authority);
|
||||
|
||||
result = proxy_h2_submit(&ts->stream_id, cf, data, ctx->h2, req,
|
||||
NULL, ts, tunnel_send_callback, cf);
|
||||
@@ -1058,7 +1023,7 @@ static CURLcode inspect_response(struct Curl_cfilter *cf,
|
||||
if(result)
|
||||
return result;
|
||||
if(data->req.newurl) {
|
||||
/* Inidicator that we should try again */
|
||||
/* Indicator that we should try again */
|
||||
Curl_safefree(data->req.newurl);
|
||||
h2_tunnel_go_state(cf, ts, H2_TUNNEL_INIT, data);
|
||||
return CURLE_OK;
|
||||
@@ -1195,6 +1160,8 @@ static void cf_h2_proxy_close(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
cf_h2_proxy_ctx_clear(ctx);
|
||||
CF_DATA_RESTORE(cf, save);
|
||||
}
|
||||
if(cf->next)
|
||||
cf->next->cft->do_close(cf->next, data);
|
||||
}
|
||||
|
||||
static void cf_h2_proxy_destroy(struct Curl_cfilter *cf,
|
||||
|
||||
@@ -781,6 +781,8 @@ struct cf_socket_ctx {
|
||||
#ifdef DEBUGBUILD
|
||||
int wblock_percent; /* percent of writes doing EAGAIN */
|
||||
int wpartial_percent; /* percent of bytes written in send */
|
||||
int rblock_percent; /* percent of reads doing EAGAIN */
|
||||
size_t recv_max; /* max enforced read size */
|
||||
#endif
|
||||
BIT(got_first_byte); /* if first byte was received */
|
||||
BIT(accepted); /* socket was accepted, not connected */
|
||||
@@ -811,6 +813,18 @@ static void cf_socket_ctx_init(struct cf_socket_ctx *ctx,
|
||||
if(l >= 0 && l <= 100)
|
||||
ctx->wpartial_percent = (int)l;
|
||||
}
|
||||
p = getenv("CURL_DBG_SOCK_RBLOCK");
|
||||
if(p) {
|
||||
long l = strtol(p, NULL, 10);
|
||||
if(l >= 0 && l <= 100)
|
||||
ctx->rblock_percent = (int)l;
|
||||
}
|
||||
p = getenv("CURL_DBG_SOCK_RMAX");
|
||||
if(p) {
|
||||
long l = strtol(p, NULL, 10);
|
||||
if(l >= 0)
|
||||
ctx->recv_max = (size_t)l;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -1358,6 +1372,27 @@ static ssize_t cf_socket_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
fdsave = cf->conn->sock[cf->sockindex];
|
||||
cf->conn->sock[cf->sockindex] = ctx->sock;
|
||||
|
||||
#ifdef DEBUGBUILD
|
||||
/* simulate network blocking/partial reads */
|
||||
if(cf->cft != &Curl_cft_udp && ctx->rblock_percent > 0) {
|
||||
unsigned char c;
|
||||
Curl_rand(data, &c, 1);
|
||||
if(c >= ((100-ctx->rblock_percent)*256/100)) {
|
||||
CURL_TRC_CF(data, cf, "recv(len=%zu) SIMULATE EWOULDBLOCK", len);
|
||||
*err = CURLE_AGAIN;
|
||||
nread = -1;
|
||||
cf->conn->sock[cf->sockindex] = fdsave;
|
||||
return nread;
|
||||
}
|
||||
}
|
||||
if(cf->cft != &Curl_cft_udp && ctx->recv_max && ctx->recv_max < len) {
|
||||
size_t orig_len = len;
|
||||
len = ctx->recv_max;
|
||||
CURL_TRC_CF(data, cf, "recv(len=%zu) SIMULATE max read of %zu bytes",
|
||||
orig_len, len);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(ctx->buffer_recv && !Curl_bufq_is_empty(&ctx->recvbuf)) {
|
||||
CURL_TRC_CF(data, cf, "recv from buffer");
|
||||
nread = Curl_bufq_read(&ctx->recvbuf, (unsigned char *)buf, len, err);
|
||||
|
||||
@@ -107,6 +107,7 @@ int Curl_conncache_init(struct conncache *connc, int size)
|
||||
connc->closure_handle = curl_easy_init();
|
||||
if(!connc->closure_handle)
|
||||
return 1; /* bad */
|
||||
connc->closure_handle->internal = true;
|
||||
|
||||
Curl_hash_init(&connc->hash, size, Curl_hash_str,
|
||||
Curl_str_key_compare, free_bundle_hash_entry);
|
||||
|
||||
@@ -634,6 +634,7 @@ evaluate:
|
||||
/* next attempt was started */
|
||||
CURL_TRC_CF(data, cf, "%s trying next", baller->name);
|
||||
++ongoing;
|
||||
Curl_expire(data, 0, EXPIRE_RUN_NOW);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -646,7 +647,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 %ld ms",
|
||||
failf(data, "Connection timeout after %" CURL_FORMAT_CURL_OFF_T " ms",
|
||||
Curl_timediff(now, data->progress.t_startsingle));
|
||||
return CURLE_OPERATION_TIMEDOUT;
|
||||
}
|
||||
@@ -823,11 +824,10 @@ static CURLcode start_connect(struct Curl_cfilter *cf,
|
||||
CURL_TRC_CF(data, cf, "created %s (timeout %"
|
||||
CURL_FORMAT_TIMEDIFF_T "ms)",
|
||||
ctx->baller[1]->name, ctx->baller[1]->timeoutms);
|
||||
Curl_expire(data, data->set.happy_eyeballs_timeout,
|
||||
EXPIRE_HAPPY_EYEBALLS);
|
||||
}
|
||||
|
||||
Curl_expire(data, data->set.happy_eyeballs_timeout,
|
||||
EXPIRE_HAPPY_EYEBALLS);
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -280,9 +280,6 @@ static CURLcode deflate_init_writer(struct Curl_easy *data,
|
||||
struct zlib_writer *zp = (struct zlib_writer *) writer;
|
||||
z_stream *z = &zp->z; /* zlib state structure */
|
||||
|
||||
if(!writer->downstream)
|
||||
return CURLE_WRITE_ERROR;
|
||||
|
||||
/* Initialize zlib */
|
||||
z->zalloc = (alloc_func) zalloc_cb;
|
||||
z->zfree = (free_func) zfree_cb;
|
||||
@@ -337,9 +334,6 @@ static CURLcode gzip_init_writer(struct Curl_easy *data,
|
||||
struct zlib_writer *zp = (struct zlib_writer *) writer;
|
||||
z_stream *z = &zp->z; /* zlib state structure */
|
||||
|
||||
if(!writer->downstream)
|
||||
return CURLE_WRITE_ERROR;
|
||||
|
||||
/* Initialize zlib */
|
||||
z->zalloc = (alloc_func) zalloc_cb;
|
||||
z->zfree = (free_func) zfree_cb;
|
||||
@@ -647,9 +641,6 @@ static CURLcode brotli_init_writer(struct Curl_easy *data,
|
||||
struct brotli_writer *bp = (struct brotli_writer *) writer;
|
||||
(void) data;
|
||||
|
||||
if(!writer->downstream)
|
||||
return CURLE_WRITE_ERROR;
|
||||
|
||||
bp->br = BrotliDecoderCreateInstance(NULL, NULL, NULL);
|
||||
return bp->br? CURLE_OK: CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
@@ -741,9 +732,6 @@ static CURLcode zstd_init_writer(struct Curl_easy *data,
|
||||
|
||||
(void)data;
|
||||
|
||||
if(!writer->downstream)
|
||||
return CURLE_WRITE_ERROR;
|
||||
|
||||
zp->zds = ZSTD_createDStream();
|
||||
zp->decomp = NULL;
|
||||
return zp->zds ? CURLE_OK : CURLE_OUT_OF_MEMORY;
|
||||
@@ -822,8 +810,9 @@ static const struct content_encoding zstd_encoding = {
|
||||
static CURLcode identity_init_writer(struct Curl_easy *data,
|
||||
struct contenc_writer *writer)
|
||||
{
|
||||
(void) data;
|
||||
return writer->downstream? CURLE_OK: CURLE_WRITE_ERROR;
|
||||
(void)data;
|
||||
(void)writer;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static CURLcode identity_unencode_write(struct Curl_easy *data,
|
||||
@@ -903,51 +892,13 @@ char *Curl_all_content_encodings(void)
|
||||
}
|
||||
|
||||
|
||||
/* Real client writer: no downstream. */
|
||||
static CURLcode client_init_writer(struct Curl_easy *data,
|
||||
struct contenc_writer *writer)
|
||||
{
|
||||
(void) data;
|
||||
return writer->downstream? CURLE_WRITE_ERROR: CURLE_OK;
|
||||
}
|
||||
|
||||
static CURLcode client_unencode_write(struct Curl_easy *data,
|
||||
struct contenc_writer *writer,
|
||||
const char *buf, size_t nbytes)
|
||||
{
|
||||
struct SingleRequest *k = &data->req;
|
||||
|
||||
(void) writer;
|
||||
|
||||
if(!nbytes || k->ignorebody)
|
||||
return CURLE_OK;
|
||||
|
||||
return Curl_client_write(data, CLIENTWRITE_BODY, (char *) buf, nbytes);
|
||||
}
|
||||
|
||||
static void client_close_writer(struct Curl_easy *data,
|
||||
struct contenc_writer *writer)
|
||||
{
|
||||
(void) data;
|
||||
(void) writer;
|
||||
}
|
||||
|
||||
static const struct content_encoding client_encoding = {
|
||||
NULL,
|
||||
NULL,
|
||||
client_init_writer,
|
||||
client_unencode_write,
|
||||
client_close_writer,
|
||||
sizeof(struct contenc_writer)
|
||||
};
|
||||
|
||||
|
||||
/* Deferred error dummy writer. */
|
||||
static CURLcode error_init_writer(struct Curl_easy *data,
|
||||
struct contenc_writer *writer)
|
||||
{
|
||||
(void) data;
|
||||
return writer->downstream? CURLE_OK: CURLE_WRITE_ERROR;
|
||||
(void)data;
|
||||
(void)writer;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static CURLcode error_unencode_write(struct Curl_easy *data,
|
||||
@@ -984,31 +935,6 @@ static const struct content_encoding error_encoding = {
|
||||
sizeof(struct contenc_writer)
|
||||
};
|
||||
|
||||
/* Create an unencoding writer stage using the given handler. */
|
||||
static struct contenc_writer *
|
||||
new_unencoding_writer(struct Curl_easy *data,
|
||||
const struct content_encoding *handler,
|
||||
struct contenc_writer *downstream,
|
||||
int order)
|
||||
{
|
||||
struct contenc_writer *writer;
|
||||
|
||||
DEBUGASSERT(handler->writersize >= sizeof(struct contenc_writer));
|
||||
writer = (struct contenc_writer *) calloc(1, handler->writersize);
|
||||
|
||||
if(writer) {
|
||||
writer->handler = handler;
|
||||
writer->downstream = downstream;
|
||||
writer->order = order;
|
||||
if(handler->init_writer(data, writer)) {
|
||||
free(writer);
|
||||
writer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return writer;
|
||||
}
|
||||
|
||||
/* Write data using an unencoding writer stack. "nbytes" is not
|
||||
allowed to be 0. */
|
||||
CURLcode Curl_unencode_write(struct Curl_easy *data,
|
||||
@@ -1017,23 +943,11 @@ CURLcode Curl_unencode_write(struct Curl_easy *data,
|
||||
{
|
||||
if(!nbytes)
|
||||
return CURLE_OK;
|
||||
if(!writer)
|
||||
return CURLE_WRITE_ERROR;
|
||||
return writer->handler->unencode_write(data, writer, buf, nbytes);
|
||||
}
|
||||
|
||||
/* Close and clean-up the connection's writer stack. */
|
||||
void Curl_unencode_cleanup(struct Curl_easy *data)
|
||||
{
|
||||
struct SingleRequest *k = &data->req;
|
||||
struct contenc_writer *writer = k->writer_stack;
|
||||
|
||||
while(writer) {
|
||||
k->writer_stack = writer->downstream;
|
||||
writer->handler->close_writer(data, writer);
|
||||
free(writer);
|
||||
writer = k->writer_stack;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find the content encoding by name. */
|
||||
static const struct content_encoding *find_encoding(const char *name,
|
||||
size_t len)
|
||||
@@ -1049,9 +963,6 @@ static const struct content_encoding *find_encoding(const char *name,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* allow no more than 5 "chained" compression steps */
|
||||
#define MAX_ENCODE_STACK 5
|
||||
|
||||
/* Set-up the unencoding stack from the Content-Encoding header value.
|
||||
* See RFC 7231 section 3.1.2.2. */
|
||||
CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
|
||||
@@ -1059,6 +970,7 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
|
||||
{
|
||||
struct SingleRequest *k = &data->req;
|
||||
unsigned int order = is_transfer? 2: 1;
|
||||
CURLcode result;
|
||||
|
||||
do {
|
||||
const char *name;
|
||||
@@ -1085,41 +997,19 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
|
||||
if(is_transfer && !data->set.http_transfer_encoding)
|
||||
/* not requested, ignore */
|
||||
return CURLE_OK;
|
||||
|
||||
encoding = find_encoding(name, namelen);
|
||||
|
||||
if(!k->writer_stack) {
|
||||
k->writer_stack = new_unencoding_writer(data, &client_encoding,
|
||||
NULL, 0);
|
||||
|
||||
if(!k->writer_stack)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if(!encoding)
|
||||
encoding = &error_encoding; /* Defer error at stack use. */
|
||||
|
||||
if(k->writer_stack_depth++ >= MAX_ENCODE_STACK) {
|
||||
failf(data, "Reject response due to more than %u content encodings",
|
||||
MAX_ENCODE_STACK);
|
||||
return CURLE_BAD_CONTENT_ENCODING;
|
||||
}
|
||||
/* Stack the unencoding stage. */
|
||||
if(order >= k->writer_stack->order) {
|
||||
writer = new_unencoding_writer(data, encoding,
|
||||
k->writer_stack, order);
|
||||
if(!writer)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
k->writer_stack = writer;
|
||||
}
|
||||
else {
|
||||
struct contenc_writer *w = k->writer_stack;
|
||||
while(w->downstream && order < w->downstream->order)
|
||||
w = w->downstream;
|
||||
writer = new_unencoding_writer(data, encoding,
|
||||
w->downstream, order);
|
||||
if(!writer)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
w->downstream = writer;
|
||||
result = Curl_client_create_writer(&writer, data, encoding, order);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
result = Curl_client_add_writer(data, writer);
|
||||
if(result) {
|
||||
Curl_client_free_writer(data, writer);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
} while(*enclist);
|
||||
@@ -1149,11 +1039,6 @@ CURLcode Curl_unencode_write(struct Curl_easy *data,
|
||||
return CURLE_NOT_BUILT_IN;
|
||||
}
|
||||
|
||||
void Curl_unencode_cleanup(struct Curl_easy *data)
|
||||
{
|
||||
(void) data;
|
||||
}
|
||||
|
||||
char *Curl_all_content_encodings(void)
|
||||
{
|
||||
return strdup(CONTENT_ENCODING_DEFAULT); /* Satisfy caller. */
|
||||
|
||||
@@ -25,26 +25,9 @@
|
||||
***************************************************************************/
|
||||
#include "curl_setup.h"
|
||||
|
||||
struct contenc_writer {
|
||||
const struct content_encoding *handler; /* Encoding handler. */
|
||||
struct contenc_writer *downstream; /* Downstream writer. */
|
||||
unsigned int order; /* Ordering within writer stack. */
|
||||
};
|
||||
|
||||
/* Content encoding writer. */
|
||||
struct content_encoding {
|
||||
const char *name; /* Encoding name. */
|
||||
const char *alias; /* Encoding name alias. */
|
||||
CURLcode (*init_writer)(struct Curl_easy *data,
|
||||
struct contenc_writer *writer);
|
||||
CURLcode (*unencode_write)(struct Curl_easy *data,
|
||||
struct contenc_writer *writer,
|
||||
const char *buf, size_t nbytes);
|
||||
void (*close_writer)(struct Curl_easy *data,
|
||||
struct contenc_writer *writer);
|
||||
size_t writersize;
|
||||
};
|
||||
struct contenc_writer;
|
||||
|
||||
char *Curl_all_content_encodings(void);
|
||||
|
||||
CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
|
||||
const char *enclist, int is_transfer);
|
||||
@@ -52,6 +35,5 @@ CURLcode Curl_unencode_write(struct Curl_easy *data,
|
||||
struct contenc_writer *writer,
|
||||
const char *buf, size_t nbytes);
|
||||
void Curl_unencode_cleanup(struct Curl_easy *data);
|
||||
char *Curl_all_content_encodings(void);
|
||||
|
||||
#endif /* HEADER_CURL_CONTENT_ENCODING_H */
|
||||
|
||||
@@ -112,14 +112,11 @@ static void strstore(char **str, const char *newstr, size_t len);
|
||||
|
||||
static void freecookie(struct Cookie *co)
|
||||
{
|
||||
free(co->expirestr);
|
||||
free(co->domain);
|
||||
free(co->path);
|
||||
free(co->spath);
|
||||
free(co->name);
|
||||
free(co->value);
|
||||
free(co->maxage);
|
||||
free(co->version);
|
||||
free(co);
|
||||
}
|
||||
|
||||
@@ -487,7 +484,7 @@ Curl_cookie_add(struct Curl_easy *data,
|
||||
struct CookieInfo *c,
|
||||
bool httpheader, /* TRUE if HTTP header-style line */
|
||||
bool noexpire, /* if TRUE, skip remove_expired() */
|
||||
char *lineptr, /* first character of the line */
|
||||
const char *lineptr, /* first character of the line */
|
||||
const char *domain, /* default domain */
|
||||
const char *path, /* full path used when this cookie is set,
|
||||
used to get default path for the cookie
|
||||
@@ -718,11 +715,7 @@ Curl_cookie_add(struct Curl_easy *data,
|
||||
}
|
||||
}
|
||||
else if((nlen == 7) && strncasecompare("version", namep, 7)) {
|
||||
strstore(&co->version, valuep, vlen);
|
||||
if(!co->version) {
|
||||
badcookie = TRUE;
|
||||
break;
|
||||
}
|
||||
/* just ignore */
|
||||
}
|
||||
else if((nlen == 7) && strncasecompare("max-age", namep, 7)) {
|
||||
/*
|
||||
@@ -734,17 +727,55 @@ Curl_cookie_add(struct Curl_easy *data,
|
||||
* client should discard the cookie. A value of zero means the
|
||||
* cookie should be discarded immediately.
|
||||
*/
|
||||
strstore(&co->maxage, valuep, vlen);
|
||||
if(!co->maxage) {
|
||||
badcookie = TRUE;
|
||||
CURLofft offt;
|
||||
const char *maxage = valuep;
|
||||
offt = curlx_strtoofft((*maxage == '\"')?
|
||||
&maxage[1]:&maxage[0], NULL, 10,
|
||||
&co->expires);
|
||||
switch(offt) {
|
||||
case CURL_OFFT_FLOW:
|
||||
/* overflow, used max value */
|
||||
co->expires = CURL_OFF_T_MAX;
|
||||
break;
|
||||
case CURL_OFFT_INVAL:
|
||||
/* negative or otherwise bad, expire */
|
||||
co->expires = 1;
|
||||
break;
|
||||
case CURL_OFFT_OK:
|
||||
if(!co->expires)
|
||||
/* already expired */
|
||||
co->expires = 1;
|
||||
else if(CURL_OFF_T_MAX - now < co->expires)
|
||||
/* would overflow */
|
||||
co->expires = CURL_OFF_T_MAX;
|
||||
else
|
||||
co->expires += now;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if((nlen == 7) && strncasecompare("expires", namep, 7)) {
|
||||
strstore(&co->expirestr, valuep, vlen);
|
||||
if(!co->expirestr) {
|
||||
badcookie = TRUE;
|
||||
break;
|
||||
char date[128];
|
||||
if(!co->expires && (vlen < sizeof(date))) {
|
||||
/* copy the date so that it can be null terminated */
|
||||
memcpy(date, valuep, vlen);
|
||||
date[vlen] = 0;
|
||||
/*
|
||||
* Let max-age have priority.
|
||||
*
|
||||
* If the date cannot get parsed for whatever reason, the cookie
|
||||
* will be treated as a session cookie
|
||||
*/
|
||||
co->expires = Curl_getdate_capped(date);
|
||||
|
||||
/*
|
||||
* Session cookies have expires set to 0 so if we get that back
|
||||
* from the date parser let's add a second to make it a
|
||||
* non-session cookie
|
||||
*/
|
||||
if(co->expires == 0)
|
||||
co->expires = 1;
|
||||
else if(co->expires < 0)
|
||||
co->expires = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -764,49 +795,6 @@ Curl_cookie_add(struct Curl_easy *data,
|
||||
break;
|
||||
} while(1);
|
||||
|
||||
if(co->maxage) {
|
||||
CURLofft offt;
|
||||
offt = curlx_strtoofft((*co->maxage == '\"')?
|
||||
&co->maxage[1]:&co->maxage[0], NULL, 10,
|
||||
&co->expires);
|
||||
switch(offt) {
|
||||
case CURL_OFFT_FLOW:
|
||||
/* overflow, used max value */
|
||||
co->expires = CURL_OFF_T_MAX;
|
||||
break;
|
||||
case CURL_OFFT_INVAL:
|
||||
/* negative or otherwise bad, expire */
|
||||
co->expires = 1;
|
||||
break;
|
||||
case CURL_OFFT_OK:
|
||||
if(!co->expires)
|
||||
/* already expired */
|
||||
co->expires = 1;
|
||||
else if(CURL_OFF_T_MAX - now < co->expires)
|
||||
/* would overflow */
|
||||
co->expires = CURL_OFF_T_MAX;
|
||||
else
|
||||
co->expires += now;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(co->expirestr) {
|
||||
/*
|
||||
* Note that if the date couldn't get parsed for whatever reason, the
|
||||
* cookie will be treated as a session cookie
|
||||
*/
|
||||
co->expires = Curl_getdate_capped(co->expirestr);
|
||||
|
||||
/*
|
||||
* Session cookies have expires set to 0 so if we get that back from the
|
||||
* date parser let's add a second to make it a non-session cookie
|
||||
*/
|
||||
if(co->expires == 0)
|
||||
co->expires = 1;
|
||||
else if(co->expires < 0)
|
||||
co->expires = 0;
|
||||
}
|
||||
|
||||
if(!badcookie && !co->domain) {
|
||||
if(domain) {
|
||||
/* no domain was given in the header line, set the default */
|
||||
@@ -894,7 +882,7 @@ Curl_cookie_add(struct Curl_easy *data,
|
||||
if(ptr)
|
||||
*ptr = 0; /* clear it */
|
||||
|
||||
firstptr = strtok_r(lineptr, "\t", &tok_buf); /* tokenize it on the TAB */
|
||||
firstptr = strtok_r((char *)lineptr, "\t", &tok_buf); /* tokenize on TAB */
|
||||
|
||||
/*
|
||||
* Now loop through the fields and init the struct we already have
|
||||
@@ -1159,9 +1147,6 @@ Curl_cookie_add(struct Curl_easy *data,
|
||||
free(clist->domain);
|
||||
free(clist->path);
|
||||
free(clist->spath);
|
||||
free(clist->expirestr);
|
||||
free(clist->version);
|
||||
free(clist->maxage);
|
||||
|
||||
*clist = *co; /* then store all the new data */
|
||||
|
||||
@@ -1224,9 +1209,6 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
|
||||
c = calloc(1, sizeof(struct CookieInfo));
|
||||
if(!c)
|
||||
return NULL; /* failed to get memory */
|
||||
c->filename = strdup(file?file:"none"); /* copy the name just in case */
|
||||
if(!c->filename)
|
||||
goto fail; /* failed to get memory */
|
||||
/*
|
||||
* Initialize the next_expiration time to signal that we don't have enough
|
||||
* information yet.
|
||||
@@ -1255,24 +1237,20 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
|
||||
|
||||
c->running = FALSE; /* this is not running, this is init */
|
||||
if(fp) {
|
||||
char *lineptr;
|
||||
bool headerline;
|
||||
|
||||
line = malloc(MAX_COOKIE_LINE);
|
||||
if(!line)
|
||||
goto fail;
|
||||
while(Curl_get_line(line, MAX_COOKIE_LINE, fp)) {
|
||||
char *lineptr = line;
|
||||
bool headerline = FALSE;
|
||||
if(checkprefix("Set-Cookie:", line)) {
|
||||
/* This is a cookie line, get it! */
|
||||
lineptr = &line[11];
|
||||
headerline = TRUE;
|
||||
while(*lineptr && ISBLANK(*lineptr))
|
||||
lineptr++;
|
||||
}
|
||||
else {
|
||||
lineptr = line;
|
||||
headerline = FALSE;
|
||||
}
|
||||
while(*lineptr && ISBLANK(*lineptr))
|
||||
lineptr++;
|
||||
|
||||
Curl_cookie_add(data, c, headerline, TRUE, lineptr, NULL, NULL, TRUE);
|
||||
}
|
||||
@@ -1288,8 +1266,8 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
|
||||
fclose(handle);
|
||||
}
|
||||
data->state.cookie_engine = TRUE;
|
||||
c->running = TRUE; /* now, we're running */
|
||||
}
|
||||
c->running = TRUE; /* now, we're running */
|
||||
|
||||
return c;
|
||||
|
||||
@@ -1371,14 +1349,11 @@ static struct Cookie *dup_cookie(struct Cookie *src)
|
||||
{
|
||||
struct Cookie *d = calloc(sizeof(struct Cookie), 1);
|
||||
if(d) {
|
||||
CLONE(expirestr);
|
||||
CLONE(domain);
|
||||
CLONE(path);
|
||||
CLONE(spath);
|
||||
CLONE(name);
|
||||
CLONE(value);
|
||||
CLONE(maxage);
|
||||
CLONE(version);
|
||||
d->expires = src->expires;
|
||||
d->tailmatch = src->tailmatch;
|
||||
d->secure = src->secure;
|
||||
@@ -1595,7 +1570,6 @@ void Curl_cookie_cleanup(struct CookieInfo *c)
|
||||
{
|
||||
if(c) {
|
||||
unsigned int i;
|
||||
free(c->filename);
|
||||
for(i = 0; i < COOKIE_HASH_SIZE; i++)
|
||||
Curl_cookie_freelist(c->cookies[i]);
|
||||
free(c); /* free the base struct as well */
|
||||
|
||||
@@ -35,12 +35,6 @@ struct Cookie {
|
||||
char *spath; /* sanitized cookie path */
|
||||
char *domain; /* domain = <this> */
|
||||
curl_off_t expires; /* expires = <this> */
|
||||
char *expirestr; /* the plain text version */
|
||||
|
||||
/* RFC 2109 keywords. Version=1 means 2109-compliant cookie sending */
|
||||
char *version; /* Version = <value> */
|
||||
char *maxage; /* Max-Age = <value> */
|
||||
|
||||
bool tailmatch; /* whether we do tail-matching of the domain name */
|
||||
bool secure; /* whether the 'secure' keyword was used */
|
||||
bool livecookie; /* updated from a server, not a stored file */
|
||||
@@ -56,17 +50,16 @@ struct Cookie {
|
||||
#define COOKIE_PREFIX__SECURE (1<<0)
|
||||
#define COOKIE_PREFIX__HOST (1<<1)
|
||||
|
||||
#define COOKIE_HASH_SIZE 256
|
||||
#define COOKIE_HASH_SIZE 63
|
||||
|
||||
struct CookieInfo {
|
||||
/* linked list of cookies we know of */
|
||||
struct Cookie *cookies[COOKIE_HASH_SIZE];
|
||||
char *filename; /* file we read from/write to */
|
||||
long numcookies; /* number of cookies in the "jar" */
|
||||
curl_off_t next_expiration; /* the next time at which expiration happens */
|
||||
int numcookies; /* number of cookies in the "jar" */
|
||||
int lastct; /* last creation-time used in the jar */
|
||||
bool running; /* state info, for cookie adding information */
|
||||
bool newsession; /* new session, discard session cookies on load */
|
||||
int lastct; /* last creation-time used in the jar */
|
||||
curl_off_t next_expiration; /* the next time at which expiration happens */
|
||||
};
|
||||
|
||||
/* The maximum sizes we accept for cookies. RFC 6265 section 6.1 says
|
||||
@@ -75,7 +68,6 @@ struct CookieInfo {
|
||||
|
||||
- At least 4096 bytes per cookie (as measured by the sum of the length of
|
||||
the cookie's name, value, and attributes).
|
||||
|
||||
In the 6265bis draft document section 5.4 it is phrased even stronger: "If
|
||||
the sum of the lengths of the name string and the value string is more than
|
||||
4096 octets, abort these steps and ignore the set-cookie-string entirely."
|
||||
@@ -116,7 +108,7 @@ struct Curl_easy;
|
||||
|
||||
struct Cookie *Curl_cookie_add(struct Curl_easy *data,
|
||||
struct CookieInfo *c, bool header,
|
||||
bool noexpiry, char *lineptr,
|
||||
bool noexpiry, const char *lineptr,
|
||||
const char *domain, const char *path,
|
||||
bool secure);
|
||||
|
||||
|
||||
@@ -152,18 +152,21 @@
|
||||
/* Define to 1 if you have the alarm function. */
|
||||
#cmakedefine HAVE_ALARM 1
|
||||
|
||||
/* Define to 1 if you have the arc4random function. */
|
||||
#cmakedefine HAVE_ARC4RANDOM 1
|
||||
|
||||
/* Define to 1 if you have the <arpa/inet.h> header file. */
|
||||
#cmakedefine HAVE_ARPA_INET_H 1
|
||||
|
||||
/* Define to 1 if you have the <arpa/tftp.h> header file. */
|
||||
#cmakedefine HAVE_ARPA_TFTP_H 1
|
||||
|
||||
/* Define to 1 if you have _Atomic support. */
|
||||
#cmakedefine HAVE_ATOMIC 1
|
||||
|
||||
/* Define to 1 if you have the `fchmod' function. */
|
||||
#cmakedefine HAVE_FCHMOD 1
|
||||
|
||||
/* Define to 1 if you have the `fnmatch' function. */
|
||||
#cmakedefine HAVE_FNMATCH 1
|
||||
|
||||
/* Define to 1 if you have the `basename' function. */
|
||||
#cmakedefine HAVE_BASENAME 1
|
||||
|
||||
@@ -176,6 +179,10 @@
|
||||
/* Define to 1 if you have the clock_gettime function and monotonic timer. */
|
||||
#cmakedefine HAVE_CLOCK_GETTIME_MONOTONIC 1
|
||||
|
||||
/* Define to 1 if you have the clock_gettime function and raw monotonic timer.
|
||||
*/
|
||||
#cmakedefine HAVE_CLOCK_GETTIME_MONOTONIC_RAW 1
|
||||
|
||||
/* Define to 1 if you have the `closesocket' function. */
|
||||
#cmakedefine HAVE_CLOSESOCKET 1
|
||||
|
||||
@@ -191,6 +198,12 @@
|
||||
/* Define to 1 if you have the freeaddrinfo function. */
|
||||
#cmakedefine HAVE_FREEADDRINFO 1
|
||||
|
||||
/* Define to 1 if you have the fseeko function. */
|
||||
#cmakedefine HAVE_FSEEKO 1
|
||||
|
||||
/* Define to 1 if you have the _fseeki64 function. */
|
||||
#cmakedefine HAVE__FSEEKI64 1
|
||||
|
||||
/* Define to 1 if you have the ftruncate function. */
|
||||
#cmakedefine HAVE_FTRUNCATE 1
|
||||
|
||||
@@ -227,9 +240,6 @@
|
||||
/* Define to 1 if you have the `getpass_r' function. */
|
||||
#cmakedefine HAVE_GETPASS_R 1
|
||||
|
||||
/* Define to 1 if you have the `getppid' function. */
|
||||
#cmakedefine HAVE_GETPPID 1
|
||||
|
||||
/* Define to 1 if you have the `getpeername' function. */
|
||||
#cmakedefine HAVE_GETPEERNAME 1
|
||||
|
||||
@@ -368,6 +378,9 @@
|
||||
# define HAVE_LONGLONG 1
|
||||
#endif
|
||||
|
||||
/* Define to 1 if you have the 'suseconds_t' data type. */
|
||||
#cmakedefine HAVE_SUSECONDS_T 1
|
||||
|
||||
/* Define to 1 if you have the MSG_NOSIGNAL flag. */
|
||||
#cmakedefine HAVE_MSG_NOSIGNAL 1
|
||||
|
||||
@@ -380,6 +393,9 @@
|
||||
/* Define to 1 if you have the <netinet/tcp.h> header file. */
|
||||
#cmakedefine HAVE_NETINET_TCP_H 1
|
||||
|
||||
/* Define to 1 if you have the <netinet/udp.h> header file. */
|
||||
#cmakedefine HAVE_NETINET_UDP_H 1
|
||||
|
||||
/* Define to 1 if you have the <linux/tcp.h> header file. */
|
||||
#cmakedefine HAVE_LINUX_TCP_H 1
|
||||
|
||||
@@ -416,9 +432,15 @@
|
||||
/* Define to 1 if you have the select function. */
|
||||
#cmakedefine HAVE_SELECT 1
|
||||
|
||||
/* Define to 1 if you have the sched_yield function. */
|
||||
#cmakedefine HAVE_SCHED_YIELD 1
|
||||
|
||||
/* Define to 1 if you have the send function. */
|
||||
#cmakedefine HAVE_SEND 1
|
||||
|
||||
/* Define to 1 if you have the sendmsg function. */
|
||||
#cmakedefine HAVE_SENDMSG 1
|
||||
|
||||
/* Define to 1 if you have the 'fsetxattr' function. */
|
||||
#cmakedefine HAVE_FSETXATTR 1
|
||||
|
||||
@@ -428,9 +450,6 @@
|
||||
/* fsetxattr() takes 6 args */
|
||||
#cmakedefine HAVE_FSETXATTR_6 1
|
||||
|
||||
/* Define to 1 if you have the <setjmp.h> header file. */
|
||||
#cmakedefine HAVE_SETJMP_H 1
|
||||
|
||||
/* Define to 1 if you have the `setlocale' function. */
|
||||
#cmakedefine HAVE_SETLOCALE 1
|
||||
|
||||
@@ -452,14 +471,11 @@
|
||||
/* Define to 1 if you have the signal function. */
|
||||
#cmakedefine HAVE_SIGNAL 1
|
||||
|
||||
/* Define to 1 if you have the <signal.h> header file. */
|
||||
#cmakedefine HAVE_SIGNAL_H 1
|
||||
|
||||
/* Define to 1 if you have the sigsetjmp function or macro. */
|
||||
#cmakedefine HAVE_SIGSETJMP 1
|
||||
|
||||
/* Define to 1 if you have the `snprintf' function. */
|
||||
#cmakedefine HAVE_SNPRINTF
|
||||
#cmakedefine HAVE_SNPRINTF 1
|
||||
|
||||
/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */
|
||||
#cmakedefine HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
|
||||
@@ -479,9 +495,6 @@
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#cmakedefine HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#cmakedefine HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the strcasecmp function. */
|
||||
#cmakedefine HAVE_STRCASECMP 1
|
||||
|
||||
@@ -500,9 +513,6 @@
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#cmakedefine HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#cmakedefine HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if you have the <stropts.h> header file. */
|
||||
#cmakedefine HAVE_STROPTS_H 1
|
||||
|
||||
@@ -512,6 +522,9 @@
|
||||
/* Define to 1 if you have the strtoll function. */
|
||||
#cmakedefine HAVE_STRTOLL 1
|
||||
|
||||
/* Define to 1 if you have the memrchr function. */
|
||||
#cmakedefine HAVE_MEMRCHR 1
|
||||
|
||||
/* if struct sockaddr_storage is defined */
|
||||
#cmakedefine HAVE_STRUCT_SOCKADDR_STORAGE 1
|
||||
|
||||
@@ -521,6 +534,9 @@
|
||||
/* Define to 1 if you have the <sys/filio.h> header file. */
|
||||
#cmakedefine HAVE_SYS_FILIO_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/wait.h> header file. */
|
||||
#cmakedefine HAVE_SYS_WAIT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/ioctl.h> header file. */
|
||||
#cmakedefine HAVE_SYS_IOCTL_H 1
|
||||
|
||||
@@ -563,9 +579,6 @@
|
||||
/* Define to 1 if you have the <termio.h> header file. */
|
||||
#cmakedefine HAVE_TERMIO_H 1
|
||||
|
||||
/* Define to 1 if you have the <time.h> header file. */
|
||||
#cmakedefine HAVE_TIME_H 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#cmakedefine HAVE_UNISTD_H 1
|
||||
|
||||
@@ -664,6 +677,9 @@ ${SIZEOF_OFF_T_CODE}
|
||||
/* The size of `curl_off_t', as computed by sizeof. */
|
||||
${SIZEOF_CURL_OFF_T_CODE}
|
||||
|
||||
/* The size of `curl_socket_t', as computed by sizeof. */
|
||||
${SIZEOF_CURL_SOCKET_T_CODE}
|
||||
|
||||
/* The size of `size_t', as computed by sizeof. */
|
||||
${SIZEOF_SIZE_T_CODE}
|
||||
|
||||
@@ -676,9 +692,6 @@ ${SIZEOF_TIME_T_CODE}
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#cmakedefine STDC_HEADERS 1
|
||||
|
||||
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
|
||||
#cmakedefine TIME_WITH_SYS_TIME 1
|
||||
|
||||
/* Define if you want to enable c-ares support */
|
||||
#cmakedefine USE_ARES 1
|
||||
|
||||
@@ -744,7 +757,7 @@ ${SIZEOF_TIME_T_CODE}
|
||||
#cmakedefine USE_MSH3 1
|
||||
|
||||
/* if Unix domain sockets are enabled */
|
||||
#cmakedefine USE_UNIX_SOCKETS
|
||||
#cmakedefine USE_UNIX_SOCKETS 1
|
||||
|
||||
/* to enable SSPI support */
|
||||
#cmakedefine USE_WINDOWS_SSPI 1
|
||||
@@ -808,3 +821,12 @@ ${SIZEOF_TIME_T_CODE}
|
||||
|
||||
/* Define to 1 to enable websocket support. */
|
||||
#cmakedefine USE_WEBSOCKETS 1
|
||||
|
||||
/* Define to 1 if OpenSSL has the SSL_CTX_set_srp_username function. */
|
||||
#cmakedefine HAVE_OPENSSL_SRP 1
|
||||
|
||||
/* Define to 1 if GnuTLS has the gnutls_srp_verifier function. */
|
||||
#cmakedefine HAVE_GNUTLS_SRP 1
|
||||
|
||||
/* Define to 1 to enable TLS-SRP support. */
|
||||
#cmakedefine USE_TLS_SRP 1
|
||||
|
||||
@@ -43,5 +43,9 @@
|
||||
#define ISDIGIT(x) (((x) >= '0') && ((x) <= '9'))
|
||||
#define ISBLANK(x) (((x) == ' ') || ((x) == '\t'))
|
||||
#define ISSPACE(x) (ISBLANK(x) || (((x) >= 0xa) && ((x) <= 0x0d)))
|
||||
#define ISURLPUNTCS(x) (((x) == '-') || ((x) == '.') || ((x) == '_') || \
|
||||
((x) == '~'))
|
||||
#define ISUNRESERVED(x) (ISALNUM(x) || ISURLPUNTCS(x))
|
||||
|
||||
|
||||
#endif /* HEADER_CURL_CTYPE_H */
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI)) \
|
||||
|| !defined(CURL_DISABLE_AWS)
|
||||
#if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI)) \
|
||||
|| !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH)
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
|
||||
@@ -28,9 +28,7 @@
|
||||
|
||||
#ifdef HAVE_MEMRCHR
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
@@ -39,9 +39,7 @@
|
||||
#ifdef HAVE_SYS_WAIT_H
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
#include <signal.h>
|
||||
#endif
|
||||
#ifdef HAVE_PWD_H
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
|
||||
@@ -28,11 +28,6 @@
|
||||
#define CURL_NO_OLDIES
|
||||
#endif
|
||||
|
||||
/* define mingw version macros, eg __MINGW{32,64}_{MINOR,MAJOR}_VERSION */
|
||||
#ifdef __MINGW32__
|
||||
#include <_mingw.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Disable Visual Studio warnings:
|
||||
* 4127 "conditional expression is constant"
|
||||
@@ -845,9 +840,6 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf,
|
||||
#endif
|
||||
|
||||
#if defined(USE_UNIX_SOCKETS) && defined(WIN32)
|
||||
# if defined(__MINGW32__) && !defined(LUP_SECURE)
|
||||
typedef u_short ADDRESS_FAMILY; /* Classic mingw, 11y+ old mingw-w64 */
|
||||
# endif
|
||||
# if !defined(UNIX_PATH_MAX)
|
||||
/* Replicating logic present in afunix.h
|
||||
(distributed with newer Windows 10 SDK versions only) */
|
||||
|
||||
@@ -70,227 +70,6 @@ extern PSecurityFunctionTable s_pSecFn;
|
||||
#define ISC_REQ_USE_HTTP_STYLE 0x01000000
|
||||
#endif
|
||||
|
||||
#ifndef ISC_RET_REPLAY_DETECT
|
||||
#define ISC_RET_REPLAY_DETECT 0x00000004
|
||||
#endif
|
||||
|
||||
#ifndef ISC_RET_SEQUENCE_DETECT
|
||||
#define ISC_RET_SEQUENCE_DETECT 0x00000008
|
||||
#endif
|
||||
|
||||
#ifndef ISC_RET_CONFIDENTIALITY
|
||||
#define ISC_RET_CONFIDENTIALITY 0x00000010
|
||||
#endif
|
||||
|
||||
#ifndef ISC_RET_ALLOCATED_MEMORY
|
||||
#define ISC_RET_ALLOCATED_MEMORY 0x00000100
|
||||
#endif
|
||||
|
||||
#ifndef ISC_RET_STREAM
|
||||
#define ISC_RET_STREAM 0x00008000
|
||||
#endif
|
||||
|
||||
#ifndef SEC_E_INSUFFICIENT_MEMORY
|
||||
# define SEC_E_INSUFFICIENT_MEMORY ((HRESULT)0x80090300L)
|
||||
#endif
|
||||
#ifndef SEC_E_INVALID_HANDLE
|
||||
# define SEC_E_INVALID_HANDLE ((HRESULT)0x80090301L)
|
||||
#endif
|
||||
#ifndef SEC_E_UNSUPPORTED_FUNCTION
|
||||
# define SEC_E_UNSUPPORTED_FUNCTION ((HRESULT)0x80090302L)
|
||||
#endif
|
||||
#ifndef SEC_E_TARGET_UNKNOWN
|
||||
# define SEC_E_TARGET_UNKNOWN ((HRESULT)0x80090303L)
|
||||
#endif
|
||||
#ifndef SEC_E_INTERNAL_ERROR
|
||||
# define SEC_E_INTERNAL_ERROR ((HRESULT)0x80090304L)
|
||||
#endif
|
||||
#ifndef SEC_E_SECPKG_NOT_FOUND
|
||||
# define SEC_E_SECPKG_NOT_FOUND ((HRESULT)0x80090305L)
|
||||
#endif
|
||||
#ifndef SEC_E_NOT_OWNER
|
||||
# define SEC_E_NOT_OWNER ((HRESULT)0x80090306L)
|
||||
#endif
|
||||
#ifndef SEC_E_CANNOT_INSTALL
|
||||
# define SEC_E_CANNOT_INSTALL ((HRESULT)0x80090307L)
|
||||
#endif
|
||||
#ifndef SEC_E_INVALID_TOKEN
|
||||
# define SEC_E_INVALID_TOKEN ((HRESULT)0x80090308L)
|
||||
#endif
|
||||
#ifndef SEC_E_CANNOT_PACK
|
||||
# define SEC_E_CANNOT_PACK ((HRESULT)0x80090309L)
|
||||
#endif
|
||||
#ifndef SEC_E_QOP_NOT_SUPPORTED
|
||||
# define SEC_E_QOP_NOT_SUPPORTED ((HRESULT)0x8009030AL)
|
||||
#endif
|
||||
#ifndef SEC_E_NO_IMPERSONATION
|
||||
# define SEC_E_NO_IMPERSONATION ((HRESULT)0x8009030BL)
|
||||
#endif
|
||||
#ifndef SEC_E_LOGON_DENIED
|
||||
# define SEC_E_LOGON_DENIED ((HRESULT)0x8009030CL)
|
||||
#endif
|
||||
#ifndef SEC_E_UNKNOWN_CREDENTIALS
|
||||
# define SEC_E_UNKNOWN_CREDENTIALS ((HRESULT)0x8009030DL)
|
||||
#endif
|
||||
#ifndef SEC_E_NO_CREDENTIALS
|
||||
# define SEC_E_NO_CREDENTIALS ((HRESULT)0x8009030EL)
|
||||
#endif
|
||||
#ifndef SEC_E_MESSAGE_ALTERED
|
||||
# define SEC_E_MESSAGE_ALTERED ((HRESULT)0x8009030FL)
|
||||
#endif
|
||||
#ifndef SEC_E_OUT_OF_SEQUENCE
|
||||
# define SEC_E_OUT_OF_SEQUENCE ((HRESULT)0x80090310L)
|
||||
#endif
|
||||
#ifndef SEC_E_NO_AUTHENTICATING_AUTHORITY
|
||||
# define SEC_E_NO_AUTHENTICATING_AUTHORITY ((HRESULT)0x80090311L)
|
||||
#endif
|
||||
#ifndef SEC_E_BAD_PKGID
|
||||
# define SEC_E_BAD_PKGID ((HRESULT)0x80090316L)
|
||||
#endif
|
||||
#ifndef SEC_E_CONTEXT_EXPIRED
|
||||
# define SEC_E_CONTEXT_EXPIRED ((HRESULT)0x80090317L)
|
||||
#endif
|
||||
#ifndef SEC_E_INCOMPLETE_MESSAGE
|
||||
# define SEC_E_INCOMPLETE_MESSAGE ((HRESULT)0x80090318L)
|
||||
#endif
|
||||
#ifndef SEC_E_INCOMPLETE_CREDENTIALS
|
||||
# define SEC_E_INCOMPLETE_CREDENTIALS ((HRESULT)0x80090320L)
|
||||
#endif
|
||||
#ifndef SEC_E_BUFFER_TOO_SMALL
|
||||
# define SEC_E_BUFFER_TOO_SMALL ((HRESULT)0x80090321L)
|
||||
#endif
|
||||
#ifndef SEC_E_WRONG_PRINCIPAL
|
||||
# define SEC_E_WRONG_PRINCIPAL ((HRESULT)0x80090322L)
|
||||
#endif
|
||||
#ifndef SEC_E_TIME_SKEW
|
||||
# define SEC_E_TIME_SKEW ((HRESULT)0x80090324L)
|
||||
#endif
|
||||
#ifndef SEC_E_UNTRUSTED_ROOT
|
||||
# define SEC_E_UNTRUSTED_ROOT ((HRESULT)0x80090325L)
|
||||
#endif
|
||||
#ifndef SEC_E_ILLEGAL_MESSAGE
|
||||
# define SEC_E_ILLEGAL_MESSAGE ((HRESULT)0x80090326L)
|
||||
#endif
|
||||
#ifndef SEC_E_CERT_UNKNOWN
|
||||
# define SEC_E_CERT_UNKNOWN ((HRESULT)0x80090327L)
|
||||
#endif
|
||||
#ifndef SEC_E_CERT_EXPIRED
|
||||
# define SEC_E_CERT_EXPIRED ((HRESULT)0x80090328L)
|
||||
#endif
|
||||
#ifndef SEC_E_ENCRYPT_FAILURE
|
||||
# define SEC_E_ENCRYPT_FAILURE ((HRESULT)0x80090329L)
|
||||
#endif
|
||||
#ifndef SEC_E_DECRYPT_FAILURE
|
||||
# define SEC_E_DECRYPT_FAILURE ((HRESULT)0x80090330L)
|
||||
#endif
|
||||
#ifndef SEC_E_ALGORITHM_MISMATCH
|
||||
# define SEC_E_ALGORITHM_MISMATCH ((HRESULT)0x80090331L)
|
||||
#endif
|
||||
#ifndef SEC_E_SECURITY_QOS_FAILED
|
||||
# define SEC_E_SECURITY_QOS_FAILED ((HRESULT)0x80090332L)
|
||||
#endif
|
||||
#ifndef SEC_E_UNFINISHED_CONTEXT_DELETED
|
||||
# define SEC_E_UNFINISHED_CONTEXT_DELETED ((HRESULT)0x80090333L)
|
||||
#endif
|
||||
#ifndef SEC_E_NO_TGT_REPLY
|
||||
# define SEC_E_NO_TGT_REPLY ((HRESULT)0x80090334L)
|
||||
#endif
|
||||
#ifndef SEC_E_NO_IP_ADDRESSES
|
||||
# define SEC_E_NO_IP_ADDRESSES ((HRESULT)0x80090335L)
|
||||
#endif
|
||||
#ifndef SEC_E_WRONG_CREDENTIAL_HANDLE
|
||||
# define SEC_E_WRONG_CREDENTIAL_HANDLE ((HRESULT)0x80090336L)
|
||||
#endif
|
||||
#ifndef SEC_E_CRYPTO_SYSTEM_INVALID
|
||||
# define SEC_E_CRYPTO_SYSTEM_INVALID ((HRESULT)0x80090337L)
|
||||
#endif
|
||||
#ifndef SEC_E_MAX_REFERRALS_EXCEEDED
|
||||
# define SEC_E_MAX_REFERRALS_EXCEEDED ((HRESULT)0x80090338L)
|
||||
#endif
|
||||
#ifndef SEC_E_MUST_BE_KDC
|
||||
# define SEC_E_MUST_BE_KDC ((HRESULT)0x80090339L)
|
||||
#endif
|
||||
#ifndef SEC_E_STRONG_CRYPTO_NOT_SUPPORTED
|
||||
# define SEC_E_STRONG_CRYPTO_NOT_SUPPORTED ((HRESULT)0x8009033AL)
|
||||
#endif
|
||||
#ifndef SEC_E_TOO_MANY_PRINCIPALS
|
||||
# define SEC_E_TOO_MANY_PRINCIPALS ((HRESULT)0x8009033BL)
|
||||
#endif
|
||||
#ifndef SEC_E_NO_PA_DATA
|
||||
# define SEC_E_NO_PA_DATA ((HRESULT)0x8009033CL)
|
||||
#endif
|
||||
#ifndef SEC_E_PKINIT_NAME_MISMATCH
|
||||
# define SEC_E_PKINIT_NAME_MISMATCH ((HRESULT)0x8009033DL)
|
||||
#endif
|
||||
#ifndef SEC_E_SMARTCARD_LOGON_REQUIRED
|
||||
# define SEC_E_SMARTCARD_LOGON_REQUIRED ((HRESULT)0x8009033EL)
|
||||
#endif
|
||||
#ifndef SEC_E_SHUTDOWN_IN_PROGRESS
|
||||
# define SEC_E_SHUTDOWN_IN_PROGRESS ((HRESULT)0x8009033FL)
|
||||
#endif
|
||||
#ifndef SEC_E_KDC_INVALID_REQUEST
|
||||
# define SEC_E_KDC_INVALID_REQUEST ((HRESULT)0x80090340L)
|
||||
#endif
|
||||
#ifndef SEC_E_KDC_UNABLE_TO_REFER
|
||||
# define SEC_E_KDC_UNABLE_TO_REFER ((HRESULT)0x80090341L)
|
||||
#endif
|
||||
#ifndef SEC_E_KDC_UNKNOWN_ETYPE
|
||||
# define SEC_E_KDC_UNKNOWN_ETYPE ((HRESULT)0x80090342L)
|
||||
#endif
|
||||
#ifndef SEC_E_UNSUPPORTED_PREAUTH
|
||||
# define SEC_E_UNSUPPORTED_PREAUTH ((HRESULT)0x80090343L)
|
||||
#endif
|
||||
#ifndef SEC_E_DELEGATION_REQUIRED
|
||||
# define SEC_E_DELEGATION_REQUIRED ((HRESULT)0x80090345L)
|
||||
#endif
|
||||
#ifndef SEC_E_BAD_BINDINGS
|
||||
# define SEC_E_BAD_BINDINGS ((HRESULT)0x80090346L)
|
||||
#endif
|
||||
#ifndef SEC_E_MULTIPLE_ACCOUNTS
|
||||
# define SEC_E_MULTIPLE_ACCOUNTS ((HRESULT)0x80090347L)
|
||||
#endif
|
||||
#ifndef SEC_E_NO_KERB_KEY
|
||||
# define SEC_E_NO_KERB_KEY ((HRESULT)0x80090348L)
|
||||
#endif
|
||||
#ifndef SEC_E_CERT_WRONG_USAGE
|
||||
# define SEC_E_CERT_WRONG_USAGE ((HRESULT)0x80090349L)
|
||||
#endif
|
||||
#ifndef SEC_E_DOWNGRADE_DETECTED
|
||||
# define SEC_E_DOWNGRADE_DETECTED ((HRESULT)0x80090350L)
|
||||
#endif
|
||||
#ifndef SEC_E_SMARTCARD_CERT_REVOKED
|
||||
# define SEC_E_SMARTCARD_CERT_REVOKED ((HRESULT)0x80090351L)
|
||||
#endif
|
||||
#ifndef SEC_E_ISSUING_CA_UNTRUSTED
|
||||
# define SEC_E_ISSUING_CA_UNTRUSTED ((HRESULT)0x80090352L)
|
||||
#endif
|
||||
#ifndef SEC_E_REVOCATION_OFFLINE_C
|
||||
# define SEC_E_REVOCATION_OFFLINE_C ((HRESULT)0x80090353L)
|
||||
#endif
|
||||
#ifndef SEC_E_PKINIT_CLIENT_FAILURE
|
||||
# define SEC_E_PKINIT_CLIENT_FAILURE ((HRESULT)0x80090354L)
|
||||
#endif
|
||||
#ifndef SEC_E_SMARTCARD_CERT_EXPIRED
|
||||
# define SEC_E_SMARTCARD_CERT_EXPIRED ((HRESULT)0x80090355L)
|
||||
#endif
|
||||
#ifndef SEC_E_NO_S4U_PROT_SUPPORT
|
||||
# define SEC_E_NO_S4U_PROT_SUPPORT ((HRESULT)0x80090356L)
|
||||
#endif
|
||||
#ifndef SEC_E_CROSSREALM_DELEGATION_FAILURE
|
||||
# define SEC_E_CROSSREALM_DELEGATION_FAILURE ((HRESULT)0x80090357L)
|
||||
#endif
|
||||
#ifndef SEC_E_REVOCATION_OFFLINE_KDC
|
||||
# define SEC_E_REVOCATION_OFFLINE_KDC ((HRESULT)0x80090358L)
|
||||
#endif
|
||||
#ifndef SEC_E_ISSUING_CA_UNTRUSTED_KDC
|
||||
# define SEC_E_ISSUING_CA_UNTRUSTED_KDC ((HRESULT)0x80090359L)
|
||||
#endif
|
||||
#ifndef SEC_E_KDC_CERT_EXPIRED
|
||||
# define SEC_E_KDC_CERT_EXPIRED ((HRESULT)0x8009035AL)
|
||||
#endif
|
||||
#ifndef SEC_E_KDC_CERT_REVOKED
|
||||
# define SEC_E_KDC_CERT_REVOKED ((HRESULT)0x8009035BL)
|
||||
#endif
|
||||
#ifndef SEC_E_INVALID_PARAMETER
|
||||
# define SEC_E_INVALID_PARAMETER ((HRESULT)0x8009035DL)
|
||||
#endif
|
||||
@@ -301,30 +80,6 @@ extern PSecurityFunctionTable s_pSecFn;
|
||||
# define SEC_E_POLICY_NLTM_ONLY ((HRESULT)0x8009035FL)
|
||||
#endif
|
||||
|
||||
#ifndef SEC_I_CONTINUE_NEEDED
|
||||
# define SEC_I_CONTINUE_NEEDED ((HRESULT)0x00090312L)
|
||||
#endif
|
||||
#ifndef SEC_I_COMPLETE_NEEDED
|
||||
# define SEC_I_COMPLETE_NEEDED ((HRESULT)0x00090313L)
|
||||
#endif
|
||||
#ifndef SEC_I_COMPLETE_AND_CONTINUE
|
||||
# define SEC_I_COMPLETE_AND_CONTINUE ((HRESULT)0x00090314L)
|
||||
#endif
|
||||
#ifndef SEC_I_LOCAL_LOGON
|
||||
# define SEC_I_LOCAL_LOGON ((HRESULT)0x00090315L)
|
||||
#endif
|
||||
#ifndef SEC_I_CONTEXT_EXPIRED
|
||||
# define SEC_I_CONTEXT_EXPIRED ((HRESULT)0x00090317L)
|
||||
#endif
|
||||
#ifndef SEC_I_INCOMPLETE_CREDENTIALS
|
||||
# define SEC_I_INCOMPLETE_CREDENTIALS ((HRESULT)0x00090320L)
|
||||
#endif
|
||||
#ifndef SEC_I_RENEGOTIATE
|
||||
# define SEC_I_RENEGOTIATE ((HRESULT)0x00090321L)
|
||||
#endif
|
||||
#ifndef SEC_I_NO_LSA_CONTEXT
|
||||
# define SEC_I_NO_LSA_CONTEXT ((HRESULT)0x00090323L)
|
||||
#endif
|
||||
#ifndef SEC_I_SIGNATURE_NEEDED
|
||||
# define SEC_I_SIGNATURE_NEEDED ((HRESULT)0x0009035CL)
|
||||
#endif
|
||||
|
||||
@@ -106,8 +106,6 @@ curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void *),
|
||||
{
|
||||
#ifdef _WIN32_WCE
|
||||
typedef HANDLE curl_win_thread_handle_t;
|
||||
#elif defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
|
||||
typedef unsigned long curl_win_thread_handle_t;
|
||||
#else
|
||||
typedef uintptr_t curl_win_thread_handle_t;
|
||||
#endif
|
||||
|
||||
@@ -40,8 +40,7 @@
|
||||
# define curl_thread_t HANDLE
|
||||
# define curl_thread_t_null (HANDLE)0
|
||||
# if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_VISTA) || \
|
||||
(_WIN32_WINNT < _WIN32_WINNT_VISTA) || \
|
||||
(defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))
|
||||
(_WIN32_WINNT < _WIN32_WINNT_VISTA)
|
||||
# define Curl_mutex_init(m) InitializeCriticalSection(m)
|
||||
# else
|
||||
# define Curl_mutex_init(m) InitializeCriticalSectionEx(m, 0, 1)
|
||||
|
||||
@@ -61,6 +61,10 @@ void Curl_debug(struct Curl_easy *data, curl_infotype type,
|
||||
"* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
|
||||
if(data->set.fdebug) {
|
||||
bool inCallback = Curl_is_in_callback(data);
|
||||
/* CURLOPT_DEBUGFUNCTION doc says the user may set CURLOPT_PRIVATE to
|
||||
distinguish their handle from internal handles. */
|
||||
if(data->internal)
|
||||
DEBUGASSERT(!data->set.private_data);
|
||||
Curl_set_in_callback(data, true);
|
||||
(void)(*data->set.fdebug)(data, type, ptr, size, data->set.debugdata);
|
||||
Curl_set_in_callback(data, inCallback);
|
||||
|
||||
@@ -242,6 +242,7 @@ static CURLcode dohprobe(struct Curl_easy *data,
|
||||
/* pass in the struct pointer via a local variable to please coverity and
|
||||
the gcc typecheck helpers */
|
||||
struct dynbuf *resp = &p->serverdoh;
|
||||
doh->internal = true;
|
||||
ERROR_CHECK_SETOPT(CURLOPT_URL, url);
|
||||
ERROR_CHECK_SETOPT(CURLOPT_DEFAULT_PROTOCOL, "https");
|
||||
ERROR_CHECK_SETOPT(CURLOPT_WRITEFUNCTION, doh_write_cb);
|
||||
@@ -307,6 +308,10 @@ static CURLcode dohprobe(struct Curl_easy *data,
|
||||
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]);
|
||||
|
||||
@@ -89,4 +89,5 @@ int Curl_dyn_vprintf(struct dynbuf *dyn, const char *format, va_list ap_save);
|
||||
#define DYN_H1_TRAILER 4096
|
||||
#define DYN_PINGPPONG_CMD (64*1024)
|
||||
#define DYN_IMAP_CMD (64*1024)
|
||||
#define DYN_MQTT_RECV (64*1024)
|
||||
#endif
|
||||
|
||||
@@ -344,6 +344,8 @@ size_t Curl_dynhds_cremove(struct dynhds *dynhds, const char *name)
|
||||
return Curl_dynhds_remove(dynhds, name, strlen(name));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
CURLcode Curl_dynhds_h1_dprint(struct dynhds *dynhds, struct dynbuf *dbuf)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
@@ -363,4 +365,3 @@ CURLcode Curl_dynhds_h1_dprint(struct dynhds *dynhds, struct dynbuf *dbuf)
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+12
-34
@@ -303,9 +303,6 @@ void curl_global_cleanup(void)
|
||||
|
||||
Curl_ssh_cleanup();
|
||||
|
||||
#ifdef USE_WOLFSSH
|
||||
(void)wolfSSH_Cleanup();
|
||||
#endif
|
||||
#ifdef DEBUGBUILD
|
||||
free(leakpointer);
|
||||
#endif
|
||||
@@ -925,9 +922,7 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
|
||||
if(data->cookies) {
|
||||
/* If cookies are enabled in the parent handle, we enable them
|
||||
in the clone as well! */
|
||||
outcurl->cookies = Curl_cookie_init(data,
|
||||
data->cookies->filename,
|
||||
outcurl->cookies,
|
||||
outcurl->cookies = Curl_cookie_init(data, NULL, outcurl->cookies,
|
||||
data->set.cookiesession);
|
||||
if(!outcurl->cookies)
|
||||
goto fail;
|
||||
@@ -1088,11 +1083,14 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
|
||||
CURLcode result = CURLE_OK;
|
||||
int oldstate;
|
||||
int newstate;
|
||||
bool recursive = FALSE;
|
||||
|
||||
if(!GOOD_EASY_HANDLE(data) || !data->conn)
|
||||
/* crazy input, don't continue */
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
|
||||
if(Curl_is_in_callback(data))
|
||||
recursive = TRUE;
|
||||
k = &data->req;
|
||||
oldstate = k->keepon & (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE);
|
||||
|
||||
@@ -1120,34 +1118,9 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
|
||||
|
||||
if(!(newstate & KEEP_RECV_PAUSE)) {
|
||||
Curl_conn_ev_data_pause(data, FALSE);
|
||||
|
||||
if(data->state.tempcount) {
|
||||
/* there are buffers for sending that can be delivered as the receive
|
||||
pausing is lifted! */
|
||||
unsigned int i;
|
||||
unsigned int count = data->state.tempcount;
|
||||
struct tempbuf writebuf[3]; /* there can only be three */
|
||||
|
||||
/* copy the structs to allow for immediate re-pausing */
|
||||
for(i = 0; i < data->state.tempcount; i++) {
|
||||
writebuf[i] = data->state.tempwrite[i];
|
||||
Curl_dyn_init(&data->state.tempwrite[i].b, DYN_PAUSE_BUFFER);
|
||||
}
|
||||
data->state.tempcount = 0;
|
||||
|
||||
for(i = 0; i < count; i++) {
|
||||
/* even if one function returns error, this loops through and frees
|
||||
all buffers */
|
||||
if(!result)
|
||||
result = Curl_client_write(data, writebuf[i].type,
|
||||
Curl_dyn_ptr(&writebuf[i].b),
|
||||
Curl_dyn_len(&writebuf[i].b));
|
||||
Curl_dyn_free(&writebuf[i].b);
|
||||
}
|
||||
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
result = Curl_client_unpause(data);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef USE_HYPER
|
||||
@@ -1184,6 +1157,11 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
|
||||
corresponding socket callback, if used */
|
||||
result = Curl_updatesocket(data);
|
||||
|
||||
if(recursive)
|
||||
/* this might have called a callback recursively which might have set this
|
||||
to false again on exit */
|
||||
Curl_set_in_callback(data, TRUE);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,13 +31,6 @@
|
||||
#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#ifndef __MINGW64_VERSION_MAJOR
|
||||
#if (__MINGW32_MAJOR_VERSION < 5) || \
|
||||
(__MINGW32_MAJOR_VERSION == 5 && __MINGW32_MINOR_VERSION == 0)
|
||||
/* mingw >= 5.0.1 defines SRWLOCK, and slightly different from MS define */
|
||||
typedef PVOID SRWLOCK, *PSRWLOCK;
|
||||
#endif
|
||||
#endif
|
||||
#ifndef SRWLOCK_INIT
|
||||
#define SRWLOCK_INIT NULL
|
||||
#endif
|
||||
|
||||
@@ -38,33 +38,6 @@
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
/* Portable character check (remember EBCDIC). Do not use isalnum() because
|
||||
its behavior is altered by the current locale.
|
||||
See https://datatracker.ietf.org/doc/html/rfc3986#section-2.3
|
||||
*/
|
||||
bool Curl_isunreserved(unsigned char in)
|
||||
{
|
||||
switch(in) {
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
case 'a': case 'b': case 'c': case 'd': case 'e':
|
||||
case 'f': case 'g': case 'h': case 'i': case 'j':
|
||||
case 'k': case 'l': case 'm': case 'n': case 'o':
|
||||
case 'p': case 'q': case 'r': case 's': case 't':
|
||||
case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
|
||||
case 'A': case 'B': case 'C': case 'D': case 'E':
|
||||
case 'F': case 'G': case 'H': case 'I': case 'J':
|
||||
case 'K': case 'L': case 'M': case 'N': case 'O':
|
||||
case 'P': case 'Q': case 'R': case 'S': case 'T':
|
||||
case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z':
|
||||
case '-': case '.': case '_': case '~':
|
||||
return TRUE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* for ABI-compatibility with previous versions */
|
||||
char *curl_escape(const char *string, int inlength)
|
||||
{
|
||||
@@ -99,7 +72,7 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string,
|
||||
while(length--) {
|
||||
unsigned char in = *string++; /* treat the characters unsigned */
|
||||
|
||||
if(Curl_isunreserved(in)) {
|
||||
if(ISUNRESERVED(in)) {
|
||||
/* append this */
|
||||
if(Curl_dyn_addn(&d, &in, 1))
|
||||
return NULL;
|
||||
@@ -233,3 +206,29 @@ void curl_free(void *p)
|
||||
{
|
||||
free(p);
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_hexencode()
|
||||
*
|
||||
* Converts binary input to lowercase hex-encoded ASCII output.
|
||||
* Null-terminated.
|
||||
*/
|
||||
void Curl_hexencode(const unsigned char *src, size_t len, /* input length */
|
||||
unsigned char *out, size_t olen) /* output buffer size */
|
||||
{
|
||||
const char *hex = "0123456789abcdef";
|
||||
DEBUGASSERT(src && len && (olen >= 3));
|
||||
if(src && len && (olen >= 3)) {
|
||||
while(len-- && (olen >= 3)) {
|
||||
/* clang-tidy warns on this line without this comment: */
|
||||
/* NOLINTNEXTLINE(clang-analyzer-core.UndefinedBinaryOperatorResult) */
|
||||
*out++ = hex[(*src & 0xF0)>>4];
|
||||
*out++ = hex[*src & 0x0F];
|
||||
++src;
|
||||
olen -= 2;
|
||||
}
|
||||
*out = 0;
|
||||
}
|
||||
else if(olen)
|
||||
*out = 0;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
/* Escape and unescape URL encoding in strings. The functions return a new
|
||||
* allocated string or NULL if an error occurred. */
|
||||
|
||||
bool Curl_isunreserved(unsigned char in);
|
||||
#include "curl_ctype.h"
|
||||
|
||||
enum urlreject {
|
||||
REJECT_NADA = 2,
|
||||
@@ -38,4 +38,7 @@ CURLcode Curl_urldecode(const char *string, size_t length,
|
||||
char **ostring, size_t *olen,
|
||||
enum urlreject ctrl);
|
||||
|
||||
void Curl_hexencode(const unsigned char *src, size_t len, /* input length */
|
||||
unsigned char *out, size_t olen); /* output buffer size */
|
||||
|
||||
#endif /* HEADER_CURL_ESCAPE_H */
|
||||
|
||||
@@ -571,7 +571,9 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
Curl_pgrsSetDownloadCounter(data, bytecount);
|
||||
result = Curl_pgrsSetDownloadCounter(data, bytecount);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
if(Curl_pgrsUpdate(data))
|
||||
result = CURLE_ABORTED_BY_CALLBACK;
|
||||
|
||||
@@ -64,7 +64,7 @@ CURLcode Curl_fopen(struct Curl_easy *data, const char *filename,
|
||||
fclose(*fh);
|
||||
*fh = NULL;
|
||||
|
||||
result = Curl_rand_hex(data, randsuffix, sizeof(randsuffix));
|
||||
result = Curl_rand_alnum(data, randsuffix, sizeof(randsuffix));
|
||||
if(result)
|
||||
goto fail;
|
||||
|
||||
|
||||
@@ -789,6 +789,20 @@ static CURLcode setname(curl_mimepart *part, const char *name, size_t len)
|
||||
return res;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
return fseeko(stream, (off_t)offset, whence);
|
||||
#elif defined(HAVE__FSEEKI64)
|
||||
return _fseeki64(stream, (__int64)offset, whence);
|
||||
#else
|
||||
if(offset > LONG_MAX)
|
||||
return -1;
|
||||
return fseek(stream, (long)offset, whence);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_getformdata() converts a linked list of "meta data" into a mime
|
||||
* structure. The input list is in 'post', while the output is stored in
|
||||
@@ -874,8 +888,7 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
|
||||
compatibility: use of "-" pseudo file name should be avoided. */
|
||||
result = curl_mime_data_cb(part, (curl_off_t) -1,
|
||||
(curl_read_callback) fread,
|
||||
CURLX_FUNCTION_CAST(curl_seek_callback,
|
||||
fseek),
|
||||
fseeko_wrapper,
|
||||
NULL, (void *) stdin);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -2067,6 +2067,31 @@ static bool ftp_213_date(const char *p, int *year, int *month, int *day,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static CURLcode client_write_header(struct Curl_easy *data,
|
||||
char *buf, size_t blen)
|
||||
{
|
||||
/* Some replies from an FTP server are written to the client
|
||||
* as CLIENTWRITE_HEADER, formatted as if they came from a
|
||||
* HTTP conversation.
|
||||
* In all protocols, CLIENTWRITE_HEADER data is only passed to
|
||||
* the body write callback when data->set.include_header is set
|
||||
* via CURLOPT_HEADER.
|
||||
* For historic reasons, FTP never played this game and expects
|
||||
* all its HEADERs to do that always. Set that flag during the
|
||||
* call to Curl_client_write() so it does the right thing.
|
||||
*
|
||||
* Notice that we cannot enable this flag for FTP in general,
|
||||
* as an FTP transfer might involve a HTTP proxy connection and
|
||||
* headers from CONNECT should not automatically be part of the
|
||||
* output. */
|
||||
CURLcode result;
|
||||
int save = data->set.include_header;
|
||||
data->set.include_header = TRUE;
|
||||
result = Curl_client_write(data, CLIENTWRITE_HEADER, buf, blen);
|
||||
data->set.include_header = save? TRUE:FALSE;
|
||||
return result;
|
||||
}
|
||||
|
||||
static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
|
||||
int ftpcode)
|
||||
{
|
||||
@@ -2120,8 +2145,7 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
|
||||
tm->tm_hour,
|
||||
tm->tm_min,
|
||||
tm->tm_sec);
|
||||
result = Curl_client_write(data, CLIENTWRITE_BOTH, headerbuf,
|
||||
headerbuflen);
|
||||
result = client_write_header(data, headerbuf, headerbuflen);
|
||||
if(result)
|
||||
return result;
|
||||
} /* end of a ridiculous amount of conditionals */
|
||||
@@ -2331,7 +2355,7 @@ static CURLcode ftp_state_size_resp(struct Curl_easy *data,
|
||||
char clbuf[128];
|
||||
int clbuflen = msnprintf(clbuf, sizeof(clbuf),
|
||||
"Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize);
|
||||
result = Curl_client_write(data, CLIENTWRITE_BOTH, clbuf, clbuflen);
|
||||
result = client_write_header(data, clbuf, clbuflen);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
@@ -2365,8 +2389,7 @@ static CURLcode ftp_state_rest_resp(struct Curl_easy *data,
|
||||
#ifdef CURL_FTP_HTTPSTYLE_HEAD
|
||||
if(ftpcode == 350) {
|
||||
char buffer[24]= { "Accept-ranges: bytes\r\n" };
|
||||
result = Curl_client_write(data, CLIENTWRITE_BOTH, buffer,
|
||||
strlen(buffer));
|
||||
result = client_write_header(data, buffer, strlen(buffer));
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
@@ -3457,7 +3480,7 @@ CURLcode ftp_sendquote(struct Curl_easy *data,
|
||||
/* if a command starts with an asterisk, which a legal FTP command never
|
||||
can, the command will be allowed to fail without it causing any
|
||||
aborts or cancels etc. It will cause libcurl to act as if the command
|
||||
is successful, whatever the server reponds. */
|
||||
is successful, whatever the server responds. */
|
||||
|
||||
if(cmd[0] == '*') {
|
||||
cmd++;
|
||||
|
||||
@@ -379,7 +379,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
|
||||
/* scenario:
|
||||
* 1. call => OK..
|
||||
* 2. call => OUT_OF_MEMORY (or other error)
|
||||
* 3. (last) call => is skipped RIGHT HERE and the error is hadled later
|
||||
* 3. (last) call => is skipped RIGHT HERE and the error is handled later
|
||||
* in wc_statemach()
|
||||
*/
|
||||
goto fail;
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI)) \
|
||||
|| !defined(CURL_DISABLE_AWS)
|
||||
#if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI)) \
|
||||
|| !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH)
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
|
||||
@@ -41,12 +41,8 @@
|
||||
#include <inet.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SETJMP_H
|
||||
#include <setjmp.h>
|
||||
#endif
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#include "urldata.h"
|
||||
#include "sendf.h"
|
||||
|
||||
@@ -30,9 +30,7 @@
|
||||
#include "timeval.h" /* for timediff_t */
|
||||
#include "asyn.h"
|
||||
|
||||
#ifdef HAVE_SETJMP_H
|
||||
#include <setjmp.h>
|
||||
#endif
|
||||
|
||||
/* Allocate enough memory to hold the full name information structs and
|
||||
* everything. OSF1 is known to require at least 8872 bytes. The buffer
|
||||
|
||||
+12
-12
@@ -1139,6 +1139,8 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
|
||||
data->state.authproblem = TRUE;
|
||||
}
|
||||
}
|
||||
#else
|
||||
;
|
||||
#endif
|
||||
|
||||
/* there may be multiple methods on one line, so keep reading */
|
||||
@@ -1157,8 +1159,6 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
|
||||
* http_should_fail() determines whether an HTTP response has gotten us
|
||||
* into an error state or not.
|
||||
*
|
||||
* @param conn all information about the current connection
|
||||
*
|
||||
* @retval FALSE communications should continue
|
||||
*
|
||||
* @retval TRUE communications should not continue
|
||||
@@ -1602,8 +1602,6 @@ CURLcode Curl_http_done(struct Curl_easy *data,
|
||||
data->state.authhost.multipass = FALSE;
|
||||
data->state.authproxy.multipass = FALSE;
|
||||
|
||||
Curl_unencode_cleanup(data);
|
||||
|
||||
/* set the proper values (possibly modified on POST) */
|
||||
conn->seek_func = data->set.seek_func; /* restore */
|
||||
conn->seek_client = data->set.seek_client; /* restore */
|
||||
@@ -3970,18 +3968,23 @@ CURLcode Curl_bump_headersize(struct Curl_easy *data,
|
||||
bool connect_only)
|
||||
{
|
||||
size_t bad = 0;
|
||||
unsigned int max = MAX_HTTP_RESP_HEADER_SIZE;
|
||||
if(delta < MAX_HTTP_RESP_HEADER_SIZE) {
|
||||
data->info.header_size += (unsigned int)delta;
|
||||
data->req.allheadercount += (unsigned int)delta;
|
||||
if(!connect_only)
|
||||
data->req.headerbytecount += (unsigned int)delta;
|
||||
data->info.header_size += (unsigned int)delta;
|
||||
if(data->info.header_size > MAX_HTTP_RESP_HEADER_SIZE)
|
||||
if(data->req.allheadercount > max)
|
||||
bad = data->req.allheadercount;
|
||||
else if(data->info.header_size > (max * 20)) {
|
||||
bad = data->info.header_size;
|
||||
max *= 20;
|
||||
}
|
||||
}
|
||||
else
|
||||
bad = data->info.header_size + delta;
|
||||
bad = data->req.allheadercount + delta;
|
||||
if(bad) {
|
||||
failf(data, "Too large response headers: %zu > %u",
|
||||
bad, MAX_HTTP_RESP_HEADER_SIZE);
|
||||
failf(data, "Too large response headers: %zu > %u", bad, max);
|
||||
return CURLE_RECV_ERROR;
|
||||
}
|
||||
return CURLE_OK;
|
||||
@@ -4231,7 +4234,6 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
||||
/* now, only output this if the header AND body are requested:
|
||||
*/
|
||||
writetype = CLIENTWRITE_HEADER |
|
||||
(data->set.include_header ? CLIENTWRITE_BODY : 0) |
|
||||
((k->httpcode/100 == 1) ? CLIENTWRITE_1XX : 0);
|
||||
|
||||
headerlen = Curl_dyn_len(&data->state.headerb);
|
||||
@@ -4563,8 +4565,6 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
||||
/*
|
||||
* End of header-checks. Write them to the client.
|
||||
*/
|
||||
if(data->set.include_header)
|
||||
writetype |= CLIENTWRITE_BODY;
|
||||
if(k->httpcode/100 == 1)
|
||||
writetype |= CLIENTWRITE_1XX;
|
||||
|
||||
|
||||
@@ -318,5 +318,29 @@ out:
|
||||
return nread;
|
||||
}
|
||||
|
||||
CURLcode Curl_h1_req_write_head(struct httpreq *req, int http_minor,
|
||||
struct dynbuf *dbuf)
|
||||
{
|
||||
CURLcode result;
|
||||
|
||||
result = Curl_dyn_addf(dbuf, "%s %s%s%s%s HTTP/1.%d\r\n",
|
||||
req->method,
|
||||
req->scheme? req->scheme : "",
|
||||
req->scheme? "://" : "",
|
||||
req->authority? req->authority : "",
|
||||
req->path? req->path : "",
|
||||
http_minor);
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
result = Curl_dynhds_h1_dprint(&req->headers, dbuf);
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
result = Curl_dyn_addn(dbuf, STRCONST("\r\n"));
|
||||
|
||||
out:
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /* !CURL_DISABLE_HTTP */
|
||||
|
||||
@@ -56,6 +56,8 @@ ssize_t Curl_h1_req_parse_read(struct h1_req_parser *parser,
|
||||
CURLcode Curl_h1_req_dprint(const struct httpreq *req,
|
||||
struct dynbuf *dbuf);
|
||||
|
||||
CURLcode Curl_h1_req_write_head(struct httpreq *req, int http_minor,
|
||||
struct dynbuf *dbuf);
|
||||
|
||||
#endif /* !CURL_DISABLE_HTTP */
|
||||
#endif /* HEADER_CURL_HTTP1_H */
|
||||
|
||||
@@ -1688,7 +1688,7 @@ static ssize_t http2_handle_stream_close(struct Curl_cfilter *cf,
|
||||
"connection", stream->id);
|
||||
connclose(cf->conn, "REFUSED_STREAM"); /* don't use this anymore */
|
||||
data->state.refused_stream = TRUE;
|
||||
*err = CURLE_SEND_ERROR; /* trigger Curl_retry_request() later */
|
||||
*err = CURLE_RECV_ERROR; /* trigger Curl_retry_request() later */
|
||||
return -1;
|
||||
}
|
||||
else if(stream->error != NGHTTP2_NO_ERROR) {
|
||||
@@ -2313,7 +2313,7 @@ out:
|
||||
"h2 windows %d-%d (stream-conn), "
|
||||
"buffers %zu-%zu (stream-conn)",
|
||||
stream->id, len, nwritten, *err,
|
||||
(ssize_t)stream->upload_left,
|
||||
stream->upload_left,
|
||||
nghttp2_session_get_stream_remote_window_size(
|
||||
ctx->h2, stream->id),
|
||||
nghttp2_session_get_remote_window_size(ctx->h2),
|
||||
@@ -2425,6 +2425,8 @@ static void cf_h2_close(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
cf_h2_ctx_clear(ctx);
|
||||
CF_DATA_RESTORE(cf, save);
|
||||
}
|
||||
if(cf->next)
|
||||
cf->next->cft->do_close(cf->next, data);
|
||||
}
|
||||
|
||||
static void cf_h2_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "transfer.h"
|
||||
#include "parsedate.h"
|
||||
#include "sendf.h"
|
||||
#include "escape.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
@@ -63,11 +64,8 @@
|
||||
|
||||
static void sha256_to_hex(char *dst, unsigned char *sha)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
|
||||
msnprintf(dst + (i * 2), SHA256_HEX_LENGTH - (i * 2), "%02x", sha[i]);
|
||||
}
|
||||
Curl_hexencode(sha, SHA256_DIGEST_LENGTH,
|
||||
(unsigned char *)dst, SHA256_HEX_LENGTH);
|
||||
}
|
||||
|
||||
static char *find_date_hdr(struct Curl_easy *data, const char *sig_hdr)
|
||||
@@ -409,6 +407,11 @@ static int compare_func(const void *a, const void *b)
|
||||
{
|
||||
const struct pair *aa = a;
|
||||
const struct pair *bb = b;
|
||||
/* If one element is empty, the other is always sorted higher */
|
||||
if(aa->len == 0)
|
||||
return -1;
|
||||
if(bb->len == 0)
|
||||
return 1;
|
||||
return strncmp(aa->p, bb->p, aa->len < bb->len ? aa->len : bb->len);
|
||||
}
|
||||
|
||||
|
||||
@@ -175,10 +175,7 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
|
||||
|
||||
/* Write the data portion available */
|
||||
if(!data->set.http_te_skip && !k->ignorebody) {
|
||||
if(!data->set.http_ce_skip && k->writer_stack)
|
||||
result = Curl_unencode_write(data, k->writer_stack, datap, piece);
|
||||
else
|
||||
result = Curl_client_write(data, CLIENTWRITE_BODY, datap, piece);
|
||||
result = Curl_client_write(data, CLIENTWRITE_BODY, datap, piece);
|
||||
|
||||
if(result) {
|
||||
*extrap = result;
|
||||
|
||||
@@ -52,6 +52,113 @@
|
||||
#include "memdebug.h"
|
||||
|
||||
|
||||
CURLcode Curl_http_proxy_get_destination(struct Curl_cfilter *cf,
|
||||
const char **phostname,
|
||||
int *pport, bool *pipv6_ip)
|
||||
{
|
||||
DEBUGASSERT(cf);
|
||||
DEBUGASSERT(cf->conn);
|
||||
|
||||
if(cf->conn->bits.conn_to_host)
|
||||
*phostname = cf->conn->conn_to_host.name;
|
||||
else if(cf->sockindex == SECONDARYSOCKET)
|
||||
*phostname = cf->conn->secondaryhostname;
|
||||
else
|
||||
*phostname = cf->conn->host.name;
|
||||
|
||||
if(cf->sockindex == SECONDARYSOCKET)
|
||||
*pport = cf->conn->secondary_port;
|
||||
else if(cf->conn->bits.conn_to_port)
|
||||
*pport = cf->conn->conn_to_port;
|
||||
else
|
||||
*pport = cf->conn->remote_port;
|
||||
|
||||
if(*phostname != cf->conn->host.name)
|
||||
*pipv6_ip = (strchr(*phostname, ':') != NULL);
|
||||
else
|
||||
*pipv6_ip = cf->conn->bits.ipv6_ip;
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
CURLcode Curl_http_proxy_create_CONNECT(struct httpreq **preq,
|
||||
struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
int http_version_major)
|
||||
{
|
||||
const char *hostname = NULL;
|
||||
char *authority = NULL;
|
||||
int port;
|
||||
bool ipv6_ip;
|
||||
CURLcode result;
|
||||
struct httpreq *req = NULL;
|
||||
|
||||
result = Curl_http_proxy_get_destination(cf, &hostname, &port, &ipv6_ip);
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
authority = aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname,
|
||||
ipv6_ip?"]":"", port);
|
||||
if(!authority) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = Curl_http_req_make(&req, "CONNECT", sizeof("CONNECT")-1,
|
||||
NULL, 0, authority, strlen(authority),
|
||||
NULL, 0);
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
/* Setup the proxy-authorization header, if any */
|
||||
result = Curl_http_output_auth(data, cf->conn, req->method, HTTPREQ_GET,
|
||||
req->authority, TRUE);
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
/* If user is not overriding Host: header, we add for HTTP/1.x */
|
||||
if(http_version_major == 1 &&
|
||||
!Curl_checkProxyheaders(data, cf->conn, STRCONST("Host"))) {
|
||||
result = Curl_dynhds_cadd(&req->headers, "Host", authority);
|
||||
if(result)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(data->state.aptr.proxyuserpwd) {
|
||||
result = Curl_dynhds_h1_cadd_line(&req->headers,
|
||||
data->state.aptr.proxyuserpwd);
|
||||
if(result)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(!Curl_checkProxyheaders(data, cf->conn, STRCONST("User-Agent"))
|
||||
&& data->set.str[STRING_USERAGENT]) {
|
||||
result = Curl_dynhds_cadd(&req->headers, "User-Agent",
|
||||
data->set.str[STRING_USERAGENT]);
|
||||
if(result)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(http_version_major == 1 &&
|
||||
!Curl_checkProxyheaders(data, cf->conn, STRCONST("Proxy-Connection"))) {
|
||||
result = Curl_dynhds_cadd(&req->headers, "Proxy-Connection", "Keep-Alive");
|
||||
if(result)
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = Curl_dynhds_add_custom(data, TRUE, &req->headers);
|
||||
|
||||
out:
|
||||
if(result && req) {
|
||||
Curl_http_req_free(req);
|
||||
req = NULL;
|
||||
}
|
||||
free(authority);
|
||||
*preq = req;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
struct cf_proxy_ctx {
|
||||
/* the protocol specific sub-filter we install during connect */
|
||||
struct Curl_cfilter *cf_protocol;
|
||||
@@ -105,7 +212,6 @@ connect_sub:
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
CURL_TRC_CF(data, cf, "installing subfilter for default HTTP/1.1");
|
||||
infof(data, "CONNECT tunnel: unsupported ALPN(%d) negotiated", alpn);
|
||||
result = CURLE_COULDNT_CONNECT;
|
||||
goto out;
|
||||
|
||||
@@ -30,6 +30,15 @@
|
||||
|
||||
#include "urldata.h"
|
||||
|
||||
CURLcode Curl_http_proxy_get_destination(struct Curl_cfilter *cf,
|
||||
const char **phostname,
|
||||
int *pport, bool *pipv6_ip);
|
||||
|
||||
CURLcode Curl_http_proxy_create_CONNECT(struct httpreq **preq,
|
||||
struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
int http_version_major);
|
||||
|
||||
/* Default proxy timeout in milliseconds */
|
||||
#define PROXY_TIMEOUT (3600*1000)
|
||||
|
||||
|
||||
@@ -91,6 +91,8 @@ static CURLcode win32_idn_to_ascii(const char *in, char **out)
|
||||
else
|
||||
return CURLE_URL_MALFORMAT;
|
||||
}
|
||||
else
|
||||
return CURLE_URL_MALFORMAT;
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
@@ -174,6 +176,9 @@ static CURLcode idn_decode(const char *input, char **output)
|
||||
if(rc != IDN2_OK)
|
||||
result = CURLE_URL_MALFORMAT;
|
||||
}
|
||||
else
|
||||
/* a too old libidn2 version */
|
||||
result = CURLE_NOT_BUILT_IN;
|
||||
#elif defined(USE_WIN32_IDN)
|
||||
result = win32_idn_to_ascii(input, &decoded);
|
||||
#endif
|
||||
|
||||
@@ -96,10 +96,10 @@ static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size)
|
||||
char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
|
||||
char *tp;
|
||||
struct {
|
||||
long base;
|
||||
long len;
|
||||
int base;
|
||||
int len;
|
||||
} best, cur;
|
||||
unsigned long words[IN6ADDRSZ / INT16SZ];
|
||||
unsigned int words[IN6ADDRSZ / INT16SZ];
|
||||
int i;
|
||||
|
||||
/* Preprocess:
|
||||
@@ -108,7 +108,7 @@ static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size)
|
||||
*/
|
||||
memset(words, '\0', sizeof(words));
|
||||
for(i = 0; i < IN6ADDRSZ; i++)
|
||||
words[i/2] |= (src[i] << ((1 - (i % 2)) << 3));
|
||||
words[i/2] |= ((unsigned int)src[i] << ((1 - (i % 2)) << 3));
|
||||
|
||||
best.base = -1;
|
||||
cur.base = -1;
|
||||
@@ -159,7 +159,7 @@ static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size)
|
||||
tp += strlen(tp);
|
||||
break;
|
||||
}
|
||||
tp += msnprintf(tp, 5, "%lx", words[i]);
|
||||
tp += msnprintf(tp, 5, "%x", words[i]);
|
||||
}
|
||||
|
||||
/* Was it a trailing run of 0x00's?
|
||||
|
||||
@@ -735,7 +735,9 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
|
||||
if(result)
|
||||
goto quit;
|
||||
dlsize++;
|
||||
Curl_pgrsSetDownloadCounter(data, dlsize);
|
||||
result = Curl_pgrsSetDownloadCounter(data, dlsize);
|
||||
if(result)
|
||||
goto quit;
|
||||
}
|
||||
|
||||
if(ber)
|
||||
|
||||
@@ -1289,9 +1289,9 @@ curl_mime *curl_mime_init(struct Curl_easy *easy)
|
||||
mime->lastpart = NULL;
|
||||
|
||||
memset(mime->boundary, '-', MIME_BOUNDARY_DASHES);
|
||||
if(Curl_rand_hex(easy,
|
||||
(unsigned char *) &mime->boundary[MIME_BOUNDARY_DASHES],
|
||||
MIME_RAND_BOUNDARY_CHARS + 1)) {
|
||||
if(Curl_rand_alnum(easy,
|
||||
(unsigned char *) &mime->boundary[MIME_BOUNDARY_DASHES],
|
||||
MIME_RAND_BOUNDARY_CHARS + 1)) {
|
||||
/* failed to get random separator, bail out */
|
||||
free(mime);
|
||||
return NULL;
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include "curl_setup.h"
|
||||
|
||||
#define MIME_BOUNDARY_DASHES 24 /* leading boundary dashes */
|
||||
#define MIME_RAND_BOUNDARY_CHARS 16 /* Nb. of random boundary chars. */
|
||||
#define MIME_RAND_BOUNDARY_CHARS 22 /* Nb. of random boundary chars. */
|
||||
#define MAX_ENCODED_LINE_LENGTH 76 /* Maximum encoded line length. */
|
||||
#define ENCODING_BUFFER_SIZE 256 /* Encoding temp buffers size. */
|
||||
|
||||
|
||||
+69
-37
@@ -109,6 +109,7 @@ static CURLcode mqtt_setup_conn(struct Curl_easy *data,
|
||||
mq = calloc(1, sizeof(struct MQTT));
|
||||
if(!mq)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
Curl_dyn_init(&mq->recvbuf, DYN_MQTT_RECV);
|
||||
data->req.p.mqtt = mq;
|
||||
return CURLE_OK;
|
||||
}
|
||||
@@ -295,12 +296,12 @@ static CURLcode mqtt_connect(struct Curl_easy *data)
|
||||
/* set initial values for the CONNECT packet */
|
||||
pos = init_connpack(packet, remain, remain_pos);
|
||||
|
||||
result = Curl_rand_hex(data, (unsigned char *)&client_id[clen],
|
||||
MQTT_CLIENTID_LEN - clen + 1);
|
||||
result = Curl_rand_alnum(data, (unsigned char *)&client_id[clen],
|
||||
MQTT_CLIENTID_LEN - clen + 1);
|
||||
/* add client id */
|
||||
rc = add_client_id(client_id, strlen(client_id), packet, pos + 1);
|
||||
if(rc) {
|
||||
failf(data, "Client ID length mismatched: [%lu]", strlen(client_id));
|
||||
failf(data, "Client ID length mismatched: [%zu]", strlen(client_id));
|
||||
result = CURLE_WEIRD_SERVER_REPLY;
|
||||
goto end;
|
||||
}
|
||||
@@ -317,7 +318,7 @@ static CURLcode mqtt_connect(struct Curl_easy *data)
|
||||
rc = add_user(username, ulen,
|
||||
(unsigned char *)packet, start_user, remain_pos);
|
||||
if(rc) {
|
||||
failf(data, "Username is too large: [%lu]", ulen);
|
||||
failf(data, "Username is too large: [%zu]", ulen);
|
||||
result = CURLE_WEIRD_SERVER_REPLY;
|
||||
goto end;
|
||||
}
|
||||
@@ -327,7 +328,7 @@ static CURLcode mqtt_connect(struct Curl_easy *data)
|
||||
if(plen) {
|
||||
rc = add_passwd(passwd, plen, packet, start_pwd, remain_pos);
|
||||
if(rc) {
|
||||
failf(data, "Password is too large: [%lu]", plen);
|
||||
failf(data, "Password is too large: [%zu]", plen);
|
||||
result = CURLE_WEIRD_SERVER_REPLY;
|
||||
goto end;
|
||||
}
|
||||
@@ -350,36 +351,66 @@ static CURLcode mqtt_disconnect(struct Curl_easy *data)
|
||||
struct MQTT *mq = data->req.p.mqtt;
|
||||
result = mqtt_send(data, (char *)"\xe0\x00", 2);
|
||||
Curl_safefree(mq->sendleftovers);
|
||||
Curl_dyn_free(&mq->recvbuf);
|
||||
return result;
|
||||
}
|
||||
|
||||
static CURLcode mqtt_recv_atleast(struct Curl_easy *data, size_t nbytes)
|
||||
{
|
||||
struct MQTT *mq = data->req.p.mqtt;
|
||||
size_t rlen = Curl_dyn_len(&mq->recvbuf);
|
||||
CURLcode result;
|
||||
|
||||
if(rlen < nbytes) {
|
||||
unsigned char readbuf[1024];
|
||||
ssize_t nread;
|
||||
|
||||
DEBUGASSERT(nbytes - rlen < sizeof(readbuf));
|
||||
result = Curl_read(data, data->conn->sock[FIRSTSOCKET],
|
||||
(char *)readbuf, nbytes - rlen, &nread);
|
||||
if(result)
|
||||
return result;
|
||||
DEBUGASSERT(nread >= 0);
|
||||
if(Curl_dyn_addn(&mq->recvbuf, readbuf, (size_t)nread))
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
rlen = Curl_dyn_len(&mq->recvbuf);
|
||||
}
|
||||
return (rlen >= nbytes)? CURLE_OK : CURLE_AGAIN;
|
||||
}
|
||||
|
||||
static void mqtt_recv_consume(struct Curl_easy *data, size_t nbytes)
|
||||
{
|
||||
struct MQTT *mq = data->req.p.mqtt;
|
||||
size_t rlen = Curl_dyn_len(&mq->recvbuf);
|
||||
if(rlen <= nbytes)
|
||||
Curl_dyn_reset(&mq->recvbuf);
|
||||
else
|
||||
Curl_dyn_tail(&mq->recvbuf, rlen - nbytes);
|
||||
}
|
||||
|
||||
static CURLcode mqtt_verify_connack(struct Curl_easy *data)
|
||||
{
|
||||
struct MQTT *mq = data->req.p.mqtt;
|
||||
CURLcode result;
|
||||
struct connectdata *conn = data->conn;
|
||||
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
|
||||
unsigned char readbuf[MQTT_CONNACK_LEN];
|
||||
ssize_t nread;
|
||||
char *ptr;
|
||||
|
||||
result = Curl_read(data, sockfd, (char *)readbuf, MQTT_CONNACK_LEN, &nread);
|
||||
result = mqtt_recv_atleast(data, MQTT_CONNACK_LEN);
|
||||
if(result)
|
||||
goto fail;
|
||||
|
||||
Curl_debug(data, CURLINFO_HEADER_IN, (char *)readbuf, (size_t)nread);
|
||||
/* verify CONNACK */
|
||||
DEBUGASSERT(Curl_dyn_len(&mq->recvbuf) >= MQTT_CONNACK_LEN);
|
||||
ptr = Curl_dyn_ptr(&mq->recvbuf);
|
||||
Curl_debug(data, CURLINFO_HEADER_IN, ptr, MQTT_CONNACK_LEN);
|
||||
|
||||
/* fixme */
|
||||
if(nread < MQTT_CONNACK_LEN) {
|
||||
if(ptr[0] != 0x00 || ptr[1] != 0x00) {
|
||||
failf(data, "Expected %02x%02x but got %02x%02x",
|
||||
0x00, 0x00, ptr[0], ptr[1]);
|
||||
Curl_dyn_reset(&mq->recvbuf);
|
||||
result = CURLE_WEIRD_SERVER_REPLY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* verify CONNACK */
|
||||
if(readbuf[0] != 0x00 || readbuf[1] != 0x00) {
|
||||
failf(data, "Expected %02x%02x but got %02x%02x",
|
||||
0x00, 0x00, readbuf[0], readbuf[1]);
|
||||
result = CURLE_WEIRD_SERVER_REPLY;
|
||||
}
|
||||
|
||||
mqtt_recv_consume(data, MQTT_CONNACK_LEN);
|
||||
fail:
|
||||
return result;
|
||||
}
|
||||
@@ -452,31 +483,29 @@ fail:
|
||||
*/
|
||||
static CURLcode mqtt_verify_suback(struct Curl_easy *data)
|
||||
{
|
||||
CURLcode result;
|
||||
struct MQTT *mq = data->req.p.mqtt;
|
||||
struct connectdata *conn = data->conn;
|
||||
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
|
||||
unsigned char readbuf[MQTT_SUBACK_LEN];
|
||||
ssize_t nread;
|
||||
struct mqtt_conn *mqtt = &conn->proto.mqtt;
|
||||
CURLcode result;
|
||||
char *ptr;
|
||||
|
||||
result = Curl_read(data, sockfd, (char *)readbuf, MQTT_SUBACK_LEN, &nread);
|
||||
result = mqtt_recv_atleast(data, MQTT_SUBACK_LEN);
|
||||
if(result)
|
||||
goto fail;
|
||||
|
||||
Curl_debug(data, CURLINFO_HEADER_IN, (char *)readbuf, (size_t)nread);
|
||||
/* verify SUBACK */
|
||||
DEBUGASSERT(Curl_dyn_len(&mq->recvbuf) >= MQTT_SUBACK_LEN);
|
||||
ptr = Curl_dyn_ptr(&mq->recvbuf);
|
||||
Curl_debug(data, CURLINFO_HEADER_IN, ptr, MQTT_SUBACK_LEN);
|
||||
|
||||
/* fixme */
|
||||
if(nread < MQTT_SUBACK_LEN) {
|
||||
if(((unsigned char)ptr[0]) != ((mqtt->packetid >> 8) & 0xff) ||
|
||||
((unsigned char)ptr[1]) != (mqtt->packetid & 0xff) ||
|
||||
ptr[2] != 0x00) {
|
||||
Curl_dyn_reset(&mq->recvbuf);
|
||||
result = CURLE_WEIRD_SERVER_REPLY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* verify SUBACK */
|
||||
if(readbuf[0] != ((mqtt->packetid >> 8) & 0xff) ||
|
||||
readbuf[1] != (mqtt->packetid & 0xff) ||
|
||||
readbuf[2] != 0x00)
|
||||
result = CURLE_WEIRD_SERVER_REPLY;
|
||||
|
||||
mqtt_recv_consume(data, MQTT_SUBACK_LEN);
|
||||
fail:
|
||||
return result;
|
||||
}
|
||||
@@ -668,7 +697,9 @@ MQTT_SUBACK_COMING:
|
||||
|
||||
mq->npacket -= nread;
|
||||
k->bytecount += nread;
|
||||
Curl_pgrsSetDownloadCounter(data, k->bytecount);
|
||||
result = Curl_pgrsSetDownloadCounter(data, k->bytecount);
|
||||
if(result)
|
||||
goto end;
|
||||
|
||||
/* if QoS is set, message contains packet id */
|
||||
|
||||
@@ -711,6 +742,7 @@ static CURLcode mqtt_done(struct Curl_easy *data,
|
||||
(void)status;
|
||||
(void)premature;
|
||||
Curl_safefree(mq->sendleftovers);
|
||||
Curl_dyn_free(&mq->recvbuf);
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ struct MQTT {
|
||||
size_t npacket; /* byte counter */
|
||||
unsigned char firstbyte;
|
||||
size_t remaining_length;
|
||||
struct dynbuf recvbuf;
|
||||
};
|
||||
|
||||
#endif /* HEADER_CURL_MQTT_H */
|
||||
|
||||
@@ -665,7 +665,6 @@ static CURLcode multi_done(struct Curl_easy *data,
|
||||
{
|
||||
CURLcode result;
|
||||
struct connectdata *conn = data->conn;
|
||||
unsigned int i;
|
||||
|
||||
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
DEBUGF(infof(data, "multi_done[%s]: status: %d prem: %d done: %d",
|
||||
@@ -721,12 +720,7 @@ static CURLcode multi_done(struct Curl_easy *data,
|
||||
|
||||
Curl_safefree(data->state.ulbuf);
|
||||
|
||||
/* if the transfer was completed in a paused state there can be buffered
|
||||
data left to free */
|
||||
for(i = 0; i < data->state.tempcount; i++) {
|
||||
Curl_dyn_free(&data->state.tempwrite[i].b);
|
||||
}
|
||||
data->state.tempcount = 0;
|
||||
Curl_client_cleanup(data);
|
||||
|
||||
CONNCACHE_LOCK(data);
|
||||
Curl_detach_connection(data);
|
||||
@@ -2131,9 +2125,11 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
}
|
||||
if(!result)
|
||||
result = protocol_connect(data, &protocol_connected);
|
||||
if(!result && !protocol_connected)
|
||||
if(!result && !protocol_connected) {
|
||||
/* switch to waiting state */
|
||||
multistate(data, MSTATE_PROTOCONNECTING);
|
||||
rc = CURLM_CALL_MULTI_PERFORM;
|
||||
}
|
||||
else if(!result) {
|
||||
/* protocol connect has completed, go WAITDO or DO */
|
||||
multistate(data, MSTATE_DO);
|
||||
@@ -2220,6 +2216,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
/* DO was not completed in one function call, we must continue
|
||||
DOING... */
|
||||
multistate(data, MSTATE_DOING);
|
||||
rc = CURLM_CALL_MULTI_PERFORM;
|
||||
}
|
||||
|
||||
/* after DO, go DO_DONE... or DO_MORE */
|
||||
@@ -2227,6 +2224,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
/* we're supposed to do more, but we need to sit down, relax
|
||||
and wait a little while first */
|
||||
multistate(data, MSTATE_DOING_MORE);
|
||||
rc = CURLM_CALL_MULTI_PERFORM;
|
||||
}
|
||||
else {
|
||||
/* we're done with the DO, now DID */
|
||||
@@ -3139,7 +3137,7 @@ static CURLMcode add_next_timeout(struct curltime now,
|
||||
struct Curl_llist_element *n = e->next;
|
||||
timediff_t diff;
|
||||
node = (struct time_node *)e->ptr;
|
||||
diff = Curl_timediff(node->time, now);
|
||||
diff = Curl_timediff_us(node->time, now);
|
||||
if(diff <= 0)
|
||||
/* remove outdated entry */
|
||||
Curl_llist_remove(list, e, NULL);
|
||||
@@ -3422,20 +3420,10 @@ static CURLMcode multi_timeout(struct Curl_multi *multi,
|
||||
|
||||
if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) {
|
||||
/* some time left before expiration */
|
||||
timediff_t diff = Curl_timediff(multi->timetree->key, now);
|
||||
if(diff <= 0)
|
||||
/*
|
||||
* Since we only provide millisecond resolution on the returned value
|
||||
* and the diff might be less than one millisecond here, we don't
|
||||
* return zero as that may cause short bursts of busyloops on fast
|
||||
* processors while the diff is still present but less than one
|
||||
* millisecond! instead we return 1 until the time is ripe.
|
||||
*/
|
||||
*timeout_ms = 1;
|
||||
else
|
||||
/* this should be safe even on 64 bit archs, as we don't use that
|
||||
overly long timeouts */
|
||||
*timeout_ms = (long)diff;
|
||||
timediff_t diff = Curl_timediff_ceil(multi->timetree->key, now);
|
||||
/* this should be safe even on 32 bit archs, as we don't use that
|
||||
overly long timeouts */
|
||||
*timeout_ms = (long)diff;
|
||||
}
|
||||
else
|
||||
/* 0 means immediately */
|
||||
@@ -3783,41 +3771,26 @@ bool Curl_is_in_callback(struct Curl_easy *easy)
|
||||
(easy->multi_easy && easy->multi_easy->in_callback));
|
||||
}
|
||||
|
||||
#ifdef DEBUGBUILD
|
||||
void Curl_multi_dump(struct Curl_multi *multi)
|
||||
{
|
||||
struct Curl_easy *data;
|
||||
int i;
|
||||
fprintf(stderr, "* Multi status: %d handles, %d alive\n",
|
||||
multi->num_easy, multi->num_alive);
|
||||
for(data = multi->easyp; data; data = data->next) {
|
||||
if(data->mstate < MSTATE_COMPLETED) {
|
||||
/* only display handles that are not completed */
|
||||
fprintf(stderr, "handle %p, state %s, %d sockets\n",
|
||||
(void *)data,
|
||||
multi_statename[data->mstate], data->numsocks);
|
||||
for(i = 0; i < data->numsocks; i++) {
|
||||
curl_socket_t s = data->sockets[i];
|
||||
struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
|
||||
|
||||
fprintf(stderr, "%d ", (int)s);
|
||||
if(!entry) {
|
||||
fprintf(stderr, "INTERNAL CONFUSION\n");
|
||||
continue;
|
||||
}
|
||||
fprintf(stderr, "[%s %s] ",
|
||||
(entry->action&CURL_POLL_IN)?"RECVING":"",
|
||||
(entry->action&CURL_POLL_OUT)?"SENDING":"");
|
||||
}
|
||||
if(data->numsocks)
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned int Curl_multi_max_concurrent_streams(struct Curl_multi *multi)
|
||||
{
|
||||
DEBUGASSERT(multi);
|
||||
return multi->max_concurrent_streams;
|
||||
}
|
||||
|
||||
struct Curl_easy **curl_multi_get_handles(struct Curl_multi *multi)
|
||||
{
|
||||
struct Curl_easy **a = malloc(sizeof(struct Curl_easy *) *
|
||||
(multi->num_easy + 1));
|
||||
if(a) {
|
||||
int i = 0;
|
||||
struct Curl_easy *e = multi->easyp;
|
||||
while(e) {
|
||||
DEBUGASSERT(i < multi->num_easy);
|
||||
if(!e->internal)
|
||||
a[i++] = e;
|
||||
e = e->next;
|
||||
}
|
||||
a[i] = NULL; /* last entry is a NULL */
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
@@ -62,15 +62,6 @@ struct Curl_multi *Curl_multi_handle(int hashsize, int chashsize,
|
||||
/* mask for checking if read and/or write is set for index x */
|
||||
#define GETSOCK_MASK_RW(x) (GETSOCK_READSOCK(x)|GETSOCK_WRITESOCK(x))
|
||||
|
||||
#ifdef DEBUGBUILD
|
||||
/*
|
||||
* Curl_multi_dump is not a stable public function, this is only meant to
|
||||
* allow easier tracking of the internal handle's state and what sockets
|
||||
* they use. Only for research and development DEBUGBUILD enabled builds.
|
||||
*/
|
||||
void Curl_multi_dump(struct Curl_multi *multi);
|
||||
#endif
|
||||
|
||||
/* Return the value of the CURLMOPT_MAX_HOST_CONNECTIONS option */
|
||||
size_t Curl_multi_max_host_connections(struct Curl_multi *multi);
|
||||
|
||||
|
||||
@@ -199,11 +199,11 @@ struct ldapreqinfo {
|
||||
};
|
||||
|
||||
/*
|
||||
* state()
|
||||
* oldap_state()
|
||||
*
|
||||
* This is the ONLY way to change LDAP state!
|
||||
*/
|
||||
static void state(struct Curl_easy *data, ldapstate newstate)
|
||||
static void oldap_state(struct Curl_easy *data, ldapstate newstate)
|
||||
{
|
||||
struct ldapconninfo *ldapc = data->conn->proto.ldapc;
|
||||
|
||||
@@ -444,7 +444,7 @@ static CURLcode oldap_perform_bind(struct Curl_easy *data, ldapstate newstate)
|
||||
rc = ldap_sasl_bind(li->ld, binddn, LDAP_SASL_SIMPLE, &passwd,
|
||||
NULL, NULL, &li->msgid);
|
||||
if(rc == LDAP_SUCCESS)
|
||||
state(data, newstate);
|
||||
oldap_state(data, newstate);
|
||||
else
|
||||
result = oldap_map_error(rc,
|
||||
data->state.aptr.user?
|
||||
@@ -467,7 +467,7 @@ static CURLcode oldap_perform_mechs(struct Curl_easy *data)
|
||||
(char **) supportedSASLMechanisms, 0,
|
||||
NULL, NULL, NULL, 0, &li->msgid);
|
||||
if(rc == LDAP_SUCCESS)
|
||||
state(data, OLDAP_MECHS);
|
||||
oldap_state(data, OLDAP_MECHS);
|
||||
else
|
||||
result = oldap_map_error(rc, CURLE_LOGIN_DENIED);
|
||||
return result;
|
||||
@@ -480,7 +480,7 @@ static CURLcode oldap_perform_sasl(struct Curl_easy *data)
|
||||
struct ldapconninfo *li = data->conn->proto.ldapc;
|
||||
CURLcode result = Curl_sasl_start(&li->sasl, data, TRUE, &progress);
|
||||
|
||||
state(data, OLDAP_SASL);
|
||||
oldap_state(data, OLDAP_SASL);
|
||||
if(!result && progress != SASL_INPROGRESS)
|
||||
result = CURLE_LOGIN_DENIED;
|
||||
return result;
|
||||
@@ -503,7 +503,7 @@ static CURLcode oldap_ssl_connect(struct Curl_easy *data, ldapstate newstate)
|
||||
|
||||
result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssldone);
|
||||
if(!result) {
|
||||
state(data, newstate);
|
||||
oldap_state(data, newstate);
|
||||
|
||||
if(ssldone) {
|
||||
Sockbuf *sb;
|
||||
@@ -527,7 +527,7 @@ static CURLcode oldap_perform_starttls(struct Curl_easy *data)
|
||||
int rc = ldap_start_tls(li->ld, NULL, NULL, &li->msgid);
|
||||
|
||||
if(rc == LDAP_SUCCESS)
|
||||
state(data, OLDAP_STARTTLS);
|
||||
oldap_state(data, OLDAP_STARTTLS);
|
||||
else
|
||||
result = oldap_map_error(rc, CURLE_USE_SSL_FAILED);
|
||||
return result;
|
||||
@@ -682,7 +682,7 @@ static CURLcode oldap_state_sasl_resp(struct Curl_easy *data,
|
||||
else {
|
||||
result = Curl_sasl_continue(&li->sasl, data, code, &progress);
|
||||
if(!result && progress != SASL_INPROGRESS)
|
||||
state(data, OLDAP_STOP);
|
||||
oldap_state(data, OLDAP_STOP);
|
||||
}
|
||||
|
||||
if(li->servercred)
|
||||
@@ -710,7 +710,7 @@ static CURLcode oldap_state_bind_resp(struct Curl_easy *data, LDAPMessage *msg,
|
||||
result = oldap_map_error(rc, CURLE_LDAP_CANNOT_BIND);
|
||||
}
|
||||
else
|
||||
state(data, OLDAP_STOP);
|
||||
oldap_state(data, OLDAP_STOP);
|
||||
|
||||
if(bv)
|
||||
ber_bvfree(bv);
|
||||
@@ -804,7 +804,8 @@ static CURLcode oldap_connecting(struct Curl_easy *data, bool *done)
|
||||
else if(data->state.aptr.user)
|
||||
result = oldap_perform_bind(data, OLDAP_BIND);
|
||||
else {
|
||||
state(data, OLDAP_STOP); /* Version 3 supported: no bind required */
|
||||
/* Version 3 supported: no bind required */
|
||||
oldap_state(data, OLDAP_STOP);
|
||||
result = CURLE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -361,7 +361,7 @@ CURLcode Curl_pp_readresp(struct Curl_easy *data,
|
||||
* for "headers". The response lines can be seen as a kind of
|
||||
* headers.
|
||||
*/
|
||||
result = Curl_client_write(data, CLIENTWRITE_HEADER,
|
||||
result = Curl_client_write(data, CLIENTWRITE_INFO,
|
||||
pp->linestart_resp, perline);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
@@ -317,9 +317,16 @@ timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize,
|
||||
/*
|
||||
* Set the number of downloaded bytes so far.
|
||||
*/
|
||||
void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size)
|
||||
CURLcode Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size)
|
||||
{
|
||||
if(data->set.max_filesize && (size > data->set.max_filesize)) {
|
||||
failf(data, "Exceeded the maximum allowed file size "
|
||||
"(%" CURL_FORMAT_CURL_OFF_T ")",
|
||||
data->set.max_filesize);
|
||||
return CURLE_FILESIZE_EXCEEDED;
|
||||
}
|
||||
data->progress.downloaded = size;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -46,7 +46,10 @@ int Curl_pgrsDone(struct Curl_easy *data);
|
||||
void Curl_pgrsStartNow(struct Curl_easy *data);
|
||||
void Curl_pgrsSetDownloadSize(struct Curl_easy *data, curl_off_t size);
|
||||
void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size);
|
||||
void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size);
|
||||
|
||||
/* It is fine to not check the return code if 'size' is set to 0 */
|
||||
CURLcode Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size);
|
||||
|
||||
void Curl_pgrsSetUploadCounter(struct Curl_easy *data, curl_off_t size);
|
||||
void Curl_ratelimit(struct Curl_easy *data, struct curltime now);
|
||||
int Curl_pgrsUpdate(struct Curl_easy *data);
|
||||
|
||||
+34
-14
@@ -24,6 +24,8 @@
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
@@ -41,6 +43,7 @@ uint32_t arc4random(void);
|
||||
#include "sendf.h"
|
||||
#include "timeval.h"
|
||||
#include "rand.h"
|
||||
#include "escape.h"
|
||||
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
@@ -49,12 +52,7 @@ uint32_t arc4random(void);
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
|
||||
# define HAVE_MINGW_ORIGINAL
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600 && \
|
||||
!defined(HAVE_MINGW_ORIGINAL)
|
||||
#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600
|
||||
# define HAVE_WIN_BCRYPTGENRANDOM
|
||||
# include <bcrypt.h>
|
||||
# ifdef _MSC_VER
|
||||
@@ -234,9 +232,7 @@ CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd,
|
||||
size_t num)
|
||||
{
|
||||
CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
const char *hex = "0123456789abcdef";
|
||||
unsigned char buffer[128];
|
||||
unsigned char *bufp = buffer;
|
||||
DEBUGASSERT(num > 1);
|
||||
|
||||
#ifdef __clang_analyzer__
|
||||
@@ -255,13 +251,37 @@ CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd,
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
Curl_hexencode(buffer, num/2, rnd, num + 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_rand_alnum() fills the 'rnd' buffer with a given 'num' size with random
|
||||
* alphanumerical chars PLUS a null-terminating byte.
|
||||
*/
|
||||
|
||||
static const char alnum[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
|
||||
CURLcode Curl_rand_alnum(struct Curl_easy *data, unsigned char *rnd,
|
||||
size_t num)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
const int alnumspace = sizeof(alnum) - 1;
|
||||
unsigned int r;
|
||||
DEBUGASSERT(num > 1);
|
||||
|
||||
num--; /* save one for null-termination */
|
||||
|
||||
while(num) {
|
||||
/* clang-tidy warns on this line without this comment: */
|
||||
/* NOLINTNEXTLINE(clang-analyzer-core.UndefinedBinaryOperatorResult) */
|
||||
*rnd++ = hex[(*bufp & 0xF0)>>4];
|
||||
*rnd++ = hex[*bufp & 0x0F];
|
||||
bufp++;
|
||||
num -= 2;
|
||||
do {
|
||||
result = randit(data, &r);
|
||||
if(result)
|
||||
return result;
|
||||
} while(r >= (UINT_MAX - UINT_MAX % alnumspace));
|
||||
|
||||
*rnd++ = alnum[r % alnumspace];
|
||||
num--;
|
||||
}
|
||||
*rnd = 0;
|
||||
|
||||
|
||||
@@ -34,6 +34,13 @@ CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num);
|
||||
CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd,
|
||||
size_t num);
|
||||
|
||||
/*
|
||||
* Curl_rand_alnum() fills the 'rnd' buffer with a given 'num' size with random
|
||||
* alphanumerical chars PLUS a null-terminating byte.
|
||||
*/
|
||||
CURLcode Curl_rand_alnum(struct Curl_easy *data, unsigned char *rnd,
|
||||
size_t num);
|
||||
|
||||
#ifdef WIN32
|
||||
/* Random generator shared between the Schannel vtls and Curl_rand*()
|
||||
functions */
|
||||
|
||||
+192
-13
@@ -40,6 +40,7 @@
|
||||
#include "sendf.h"
|
||||
#include "cfilters.h"
|
||||
#include "connect.h"
|
||||
#include "content_encoding.h"
|
||||
#include "vtls/vtls.h"
|
||||
#include "vssh/ssh.h"
|
||||
#include "easyif.h"
|
||||
@@ -213,6 +214,7 @@ CURLcode Curl_write(struct Curl_easy *data,
|
||||
|
||||
static CURLcode pausewrite(struct Curl_easy *data,
|
||||
int type, /* what type of data */
|
||||
bool paused_body,
|
||||
const char *ptr,
|
||||
size_t len)
|
||||
{
|
||||
@@ -228,7 +230,8 @@ static CURLcode pausewrite(struct Curl_easy *data,
|
||||
|
||||
if(s->tempcount) {
|
||||
for(i = 0; i< s->tempcount; i++) {
|
||||
if(s->tempwrite[i].type == type) {
|
||||
if(s->tempwrite[i].type == type &&
|
||||
!!s->tempwrite[i].paused_body == !!paused_body) {
|
||||
/* data for this type exists */
|
||||
newtype = FALSE;
|
||||
break;
|
||||
@@ -246,6 +249,7 @@ static CURLcode pausewrite(struct Curl_easy *data,
|
||||
/* store this information in the state struct for later use */
|
||||
Curl_dyn_init(&s->tempwrite[i].b, DYN_PAUSE_BUFFER);
|
||||
s->tempwrite[i].type = type;
|
||||
s->tempwrite[i].paused_body = paused_body;
|
||||
s->tempcount++;
|
||||
}
|
||||
|
||||
@@ -265,6 +269,7 @@ static CURLcode pausewrite(struct Curl_easy *data,
|
||||
*/
|
||||
static CURLcode chop_write(struct Curl_easy *data,
|
||||
int type,
|
||||
bool skip_body_write,
|
||||
char *optr,
|
||||
size_t olen)
|
||||
{
|
||||
@@ -281,10 +286,12 @@ static CURLcode chop_write(struct Curl_easy *data,
|
||||
/* If reading is paused, append this data to the already held data for this
|
||||
type. */
|
||||
if(data->req.keepon & KEEP_RECV_PAUSE)
|
||||
return pausewrite(data, type, ptr, len);
|
||||
return pausewrite(data, type, !skip_body_write, ptr, len);
|
||||
|
||||
/* Determine the callback(s) to use. */
|
||||
if(type & CLIENTWRITE_BODY) {
|
||||
if(!skip_body_write &&
|
||||
((type & CLIENTWRITE_BODY) ||
|
||||
((type & CLIENTWRITE_HEADER) && data->set.include_header))) {
|
||||
#ifdef USE_WEBSOCKETS
|
||||
if(conn->handler->protocol & (CURLPROTO_WS|CURLPROTO_WSS)) {
|
||||
writebody = Curl_ws_writecb;
|
||||
@@ -294,7 +301,7 @@ static CURLcode chop_write(struct Curl_easy *data,
|
||||
#endif
|
||||
writebody = data->set.fwrite_func;
|
||||
}
|
||||
if((type & CLIENTWRITE_HEADER) &&
|
||||
if((type & (CLIENTWRITE_HEADER|CLIENTWRITE_INFO)) &&
|
||||
(data->set.fwrite_header || data->set.writeheader)) {
|
||||
/*
|
||||
* Write headers to the same callback or to the especially setup
|
||||
@@ -322,7 +329,7 @@ static CURLcode chop_write(struct Curl_easy *data,
|
||||
failf(data, "Write callback asked for PAUSE when not supported");
|
||||
return CURLE_WRITE_ERROR;
|
||||
}
|
||||
return pausewrite(data, type, ptr, len);
|
||||
return pausewrite(data, type, TRUE, ptr, len);
|
||||
}
|
||||
if(wrote != chunklen) {
|
||||
failf(data, "Failure writing output to destination");
|
||||
@@ -357,13 +364,7 @@ static CURLcode chop_write(struct Curl_easy *data,
|
||||
Curl_set_in_callback(data, false);
|
||||
|
||||
if(CURL_WRITEFUNC_PAUSE == wrote)
|
||||
/* here we pass in the HEADER bit only since if this was body as well
|
||||
then it was passed already and clearly that didn't trigger the
|
||||
pause, so this is saved for later with the HEADER bit only */
|
||||
return pausewrite(data, CLIENTWRITE_HEADER |
|
||||
(type & (CLIENTWRITE_STATUS|CLIENTWRITE_CONNECT|
|
||||
CLIENTWRITE_1XX|CLIENTWRITE_TRAILER)),
|
||||
optr, olen);
|
||||
return pausewrite(data, type, FALSE, optr, olen);
|
||||
if(wrote != olen) {
|
||||
failf(data, "Failed writing header");
|
||||
return CURLE_WRITE_ERROR;
|
||||
@@ -397,9 +398,187 @@ CURLcode Curl_client_write(struct Curl_easy *data,
|
||||
len = convert_lineends(data, ptr, len);
|
||||
}
|
||||
#endif
|
||||
return chop_write(data, type, ptr, len);
|
||||
/* it is one of those, at least */
|
||||
DEBUGASSERT(type & (CLIENTWRITE_BODY|CLIENTWRITE_HEADER|CLIENTWRITE_INFO));
|
||||
/* BODY is only BODY */
|
||||
DEBUGASSERT(!(type & CLIENTWRITE_BODY) || (type == CLIENTWRITE_BODY));
|
||||
/* INFO is only INFO */
|
||||
DEBUGASSERT(!(type & CLIENTWRITE_INFO) || (type == CLIENTWRITE_INFO));
|
||||
|
||||
if(type == CLIENTWRITE_BODY) {
|
||||
if(data->req.ignorebody)
|
||||
return CURLE_OK;
|
||||
|
||||
if(data->req.writer_stack && !data->set.http_ce_skip)
|
||||
return Curl_unencode_write(data, data->req.writer_stack, ptr, len);
|
||||
}
|
||||
return chop_write(data, type, FALSE, ptr, len);
|
||||
}
|
||||
|
||||
CURLcode Curl_client_unpause(struct Curl_easy *data)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
if(data->state.tempcount) {
|
||||
/* there are buffers for sending that can be delivered as the receive
|
||||
pausing is lifted! */
|
||||
unsigned int i;
|
||||
unsigned int count = data->state.tempcount;
|
||||
struct tempbuf writebuf[3]; /* there can only be three */
|
||||
|
||||
/* copy the structs to allow for immediate re-pausing */
|
||||
for(i = 0; i < data->state.tempcount; i++) {
|
||||
writebuf[i] = data->state.tempwrite[i];
|
||||
Curl_dyn_init(&data->state.tempwrite[i].b, DYN_PAUSE_BUFFER);
|
||||
}
|
||||
data->state.tempcount = 0;
|
||||
|
||||
for(i = 0; i < count; i++) {
|
||||
/* even if one function returns error, this loops through and frees
|
||||
all buffers */
|
||||
if(!result)
|
||||
result = chop_write(data, writebuf[i].type,
|
||||
!writebuf[i].paused_body,
|
||||
Curl_dyn_ptr(&writebuf[i].b),
|
||||
Curl_dyn_len(&writebuf[i].b));
|
||||
Curl_dyn_free(&writebuf[i].b);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void Curl_client_cleanup(struct Curl_easy *data)
|
||||
{
|
||||
struct contenc_writer *writer = data->req.writer_stack;
|
||||
size_t i;
|
||||
|
||||
while(writer) {
|
||||
data->req.writer_stack = writer->downstream;
|
||||
writer->handler->close_writer(data, writer);
|
||||
free(writer);
|
||||
writer = data->req.writer_stack;
|
||||
}
|
||||
|
||||
for(i = 0; i < data->state.tempcount; i++) {
|
||||
Curl_dyn_free(&data->state.tempwrite[i].b);
|
||||
}
|
||||
data->state.tempcount = 0;
|
||||
|
||||
}
|
||||
|
||||
/* Real client writer: no downstream. */
|
||||
static CURLcode client_cew_init(struct Curl_easy *data,
|
||||
struct contenc_writer *writer)
|
||||
{
|
||||
(void) data;
|
||||
(void)writer;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static CURLcode client_cew_write(struct Curl_easy *data,
|
||||
struct contenc_writer *writer,
|
||||
const char *buf, size_t nbytes)
|
||||
{
|
||||
(void)writer;
|
||||
if(!nbytes || data->req.ignorebody)
|
||||
return CURLE_OK;
|
||||
return chop_write(data, CLIENTWRITE_BODY, FALSE, (char *)buf, nbytes);
|
||||
}
|
||||
|
||||
static void client_cew_close(struct Curl_easy *data,
|
||||
struct contenc_writer *writer)
|
||||
{
|
||||
(void) data;
|
||||
(void) writer;
|
||||
}
|
||||
|
||||
static const struct content_encoding client_cew = {
|
||||
NULL,
|
||||
NULL,
|
||||
client_cew_init,
|
||||
client_cew_write,
|
||||
client_cew_close,
|
||||
sizeof(struct contenc_writer)
|
||||
};
|
||||
|
||||
/* Create an unencoding writer stage using the given handler. */
|
||||
CURLcode Curl_client_create_writer(struct contenc_writer **pwriter,
|
||||
struct Curl_easy *data,
|
||||
const struct content_encoding *ce_handler,
|
||||
int order)
|
||||
{
|
||||
struct contenc_writer *writer;
|
||||
CURLcode result = CURLE_OUT_OF_MEMORY;
|
||||
|
||||
DEBUGASSERT(ce_handler->writersize >= sizeof(struct contenc_writer));
|
||||
writer = (struct contenc_writer *) calloc(1, ce_handler->writersize);
|
||||
if(!writer)
|
||||
goto out;
|
||||
|
||||
writer->handler = ce_handler;
|
||||
writer->order = order;
|
||||
result = ce_handler->init_writer(data, writer);
|
||||
|
||||
out:
|
||||
*pwriter = result? NULL : writer;
|
||||
if(result)
|
||||
free(writer);
|
||||
return result;
|
||||
}
|
||||
|
||||
void Curl_client_free_writer(struct Curl_easy *data,
|
||||
struct contenc_writer *writer)
|
||||
{
|
||||
if(writer) {
|
||||
writer->handler->close_writer(data, writer);
|
||||
free(writer);
|
||||
}
|
||||
}
|
||||
|
||||
/* allow no more than 5 "chained" compression steps */
|
||||
#define MAX_ENCODE_STACK 5
|
||||
|
||||
|
||||
static CURLcode init_writer_stack(struct Curl_easy *data)
|
||||
{
|
||||
DEBUGASSERT(!data->req.writer_stack);
|
||||
return Curl_client_create_writer(&data->req.writer_stack,
|
||||
data, &client_cew, 0);
|
||||
}
|
||||
|
||||
CURLcode Curl_client_add_writer(struct Curl_easy *data,
|
||||
struct contenc_writer *writer)
|
||||
{
|
||||
CURLcode result;
|
||||
|
||||
if(!data->req.writer_stack) {
|
||||
result = init_writer_stack(data);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
if(data->req.writer_stack_depth++ >= MAX_ENCODE_STACK) {
|
||||
failf(data, "Reject response due to more than %u content encodings",
|
||||
MAX_ENCODE_STACK);
|
||||
return CURLE_BAD_CONTENT_ENCODING;
|
||||
}
|
||||
|
||||
/* Stack the unencoding stage. */
|
||||
if(writer->order >= data->req.writer_stack->order) {
|
||||
writer->downstream = data->req.writer_stack;
|
||||
data->req.writer_stack = writer;
|
||||
}
|
||||
else {
|
||||
struct contenc_writer *w = data->req.writer_stack;
|
||||
while(w->downstream && writer->order < w->downstream->order)
|
||||
w = w->downstream;
|
||||
writer->downstream = w->downstream;
|
||||
w->downstream = writer;
|
||||
}
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Internal read-from-socket function. This is meant to deal with plain
|
||||
* sockets, SSL sockets and kerberos sockets.
|
||||
|
||||
@@ -28,18 +28,67 @@
|
||||
|
||||
#include "curl_trc.h"
|
||||
|
||||
|
||||
#define CLIENTWRITE_BODY (1<<0)
|
||||
#define CLIENTWRITE_HEADER (1<<1)
|
||||
#define CLIENTWRITE_STATUS (1<<2) /* the first "header" is the status line */
|
||||
#define CLIENTWRITE_CONNECT (1<<3) /* a CONNECT response */
|
||||
#define CLIENTWRITE_1XX (1<<4) /* a 1xx response */
|
||||
#define CLIENTWRITE_TRAILER (1<<5) /* a trailer header */
|
||||
#define CLIENTWRITE_BOTH (CLIENTWRITE_BODY|CLIENTWRITE_HEADER)
|
||||
/**
|
||||
* Type of data that is being written to the client (application)
|
||||
* - data written can be either BODY or META data
|
||||
* - META data is either INFO or HEADER
|
||||
* - INFO is meta information, e.g. not BODY, that cannot be interpreted
|
||||
* as headers of a response. Example FTP/IMAP pingpong answers.
|
||||
* - HEADER can have additional bits set (more than one)
|
||||
* - STATUS special "header", e.g. response status line in HTTP
|
||||
* - CONNECT header was received during proxying the connection
|
||||
* - 1XX header is part of an intermediate response, e.g. HTTP 1xx code
|
||||
* - TRAILER header is trailing response data, e.g. HTTP trailers
|
||||
* BODY, INFO and HEADER should not be mixed, as this would lead to
|
||||
* confusion on how to interpret/format/convert the data.
|
||||
*/
|
||||
#define CLIENTWRITE_BODY (1<<0) /* non-meta information, BODY */
|
||||
#define CLIENTWRITE_INFO (1<<1) /* meta information, not a HEADER */
|
||||
#define CLIENTWRITE_HEADER (1<<2) /* meta information, HEADER */
|
||||
#define CLIENTWRITE_STATUS (1<<3) /* a special status HEADER */
|
||||
#define CLIENTWRITE_CONNECT (1<<4) /* a CONNECT related HEADER */
|
||||
#define CLIENTWRITE_1XX (1<<5) /* a 1xx response related HEADER */
|
||||
#define CLIENTWRITE_TRAILER (1<<6) /* a trailer HEADER */
|
||||
|
||||
CURLcode Curl_client_write(struct Curl_easy *data, int type, char *ptr,
|
||||
size_t len) WARN_UNUSED_RESULT;
|
||||
|
||||
CURLcode Curl_client_unpause(struct Curl_easy *data);
|
||||
void Curl_client_cleanup(struct Curl_easy *data);
|
||||
|
||||
struct contenc_writer {
|
||||
const struct content_encoding *handler; /* Encoding handler. */
|
||||
struct contenc_writer *downstream; /* Downstream writer. */
|
||||
unsigned int order; /* Ordering within writer stack. */
|
||||
};
|
||||
|
||||
/* Content encoding writer. */
|
||||
struct content_encoding {
|
||||
const char *name; /* Encoding name. */
|
||||
const char *alias; /* Encoding name alias. */
|
||||
CURLcode (*init_writer)(struct Curl_easy *data,
|
||||
struct contenc_writer *writer);
|
||||
CURLcode (*unencode_write)(struct Curl_easy *data,
|
||||
struct contenc_writer *writer,
|
||||
const char *buf, size_t nbytes);
|
||||
void (*close_writer)(struct Curl_easy *data,
|
||||
struct contenc_writer *writer);
|
||||
size_t writersize;
|
||||
};
|
||||
|
||||
|
||||
CURLcode Curl_client_create_writer(struct contenc_writer **pwriter,
|
||||
struct Curl_easy *data,
|
||||
const struct content_encoding *ce_handler,
|
||||
int order);
|
||||
|
||||
void Curl_client_free_writer(struct Curl_easy *data,
|
||||
struct contenc_writer *writer);
|
||||
|
||||
CURLcode Curl_client_add_writer(struct Curl_easy *data,
|
||||
struct contenc_writer *writer);
|
||||
|
||||
|
||||
/* internal read-function, does plain socket, SSL and krb4 */
|
||||
CURLcode Curl_read(struct Curl_easy *data, curl_socket_t sockfd,
|
||||
char *buf, size_t buffersize,
|
||||
|
||||
@@ -2076,7 +2076,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
else
|
||||
#endif
|
||||
result = CURLE_NOT_BUILT_IN;
|
||||
break;
|
||||
break;
|
||||
case CURLOPT_PINNEDPUBLICKEY:
|
||||
/*
|
||||
* Set pinned public key for SSL connection.
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
***************************************************************************/
|
||||
#include "curl_setup.h"
|
||||
|
||||
#if defined(HAVE_SIGNAL_H) && defined(HAVE_SIGACTION) && \
|
||||
#if defined(HAVE_SIGACTION) && \
|
||||
(defined(USE_OPENSSL) || defined(USE_MBEDTLS) || defined(USE_WOLFSSL))
|
||||
#include <signal.h>
|
||||
|
||||
|
||||
@@ -1049,7 +1049,12 @@ static CURLcode smb_request_state(struct Curl_easy *data, bool *done)
|
||||
}
|
||||
data->req.bytecount += len;
|
||||
data->req.offset += len;
|
||||
Curl_pgrsSetDownloadCounter(data, data->req.bytecount);
|
||||
result = Curl_pgrsSetDownloadCounter(data, data->req.bytecount);
|
||||
if(result) {
|
||||
req->result = result;
|
||||
next_state = SMB_CLOSE;
|
||||
break;
|
||||
}
|
||||
next_state = (len < MAX_PAYLOAD_SIZE) ? SMB_CLOSE : SMB_DOWNLOAD;
|
||||
break;
|
||||
|
||||
|
||||
@@ -587,9 +587,9 @@ static CURLproxycode do_SOCKS5(struct Curl_cfilter *cf,
|
||||
|
||||
/* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */
|
||||
if(!socks5_resolve_local && hostname_len > 255) {
|
||||
infof(data, "SOCKS5: server resolving disabled for hostnames of "
|
||||
"length > 255 [actual len=%zu]", hostname_len);
|
||||
socks5_resolve_local = TRUE;
|
||||
failf(data, "SOCKS5: the destination hostname is too long to be "
|
||||
"resolved remotely by the proxy.");
|
||||
return CURLPX_LONG_HOSTNAME;
|
||||
}
|
||||
|
||||
if(auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI))
|
||||
@@ -903,7 +903,7 @@ CONNECT_RESOLVE_REMOTE:
|
||||
}
|
||||
else {
|
||||
socksreq[len++] = 3;
|
||||
socksreq[len++] = (char) hostname_len; /* one byte address length */
|
||||
socksreq[len++] = (unsigned char) hostname_len; /* one byte length */
|
||||
memcpy(&socksreq[len], sx->hostname, hostname_len); /* w/o NULL */
|
||||
len += hostname_len;
|
||||
}
|
||||
|
||||
@@ -1570,8 +1570,9 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
|
||||
}
|
||||
|
||||
total_dl += nread;
|
||||
Curl_pgrsSetDownloadCounter(data, total_dl);
|
||||
result = telrcv(data, (unsigned char *)buf, nread);
|
||||
result = Curl_pgrsSetDownloadCounter(data, total_dl);
|
||||
if(!result)
|
||||
result = telrcv(data, (unsigned char *)buf, nread);
|
||||
if(result) {
|
||||
keepon = FALSE;
|
||||
break;
|
||||
|
||||
@@ -1141,12 +1141,15 @@ static CURLcode tftp_receive_packet(struct Curl_easy *data)
|
||||
result = Curl_client_write(data, CLIENTWRITE_BODY,
|
||||
(char *)state->rpacket.data + 4,
|
||||
state->rbytes-4);
|
||||
if(!result) {
|
||||
k->bytecount += state->rbytes-4;
|
||||
result = Curl_pgrsSetDownloadCounter(data,
|
||||
(curl_off_t) k->bytecount);
|
||||
}
|
||||
if(result) {
|
||||
tftp_state_machine(state, TFTP_EVENT_ERROR);
|
||||
return result;
|
||||
}
|
||||
k->bytecount += state->rbytes-4;
|
||||
Curl_pgrsSetDownloadCounter(data, (curl_off_t) k->bytecount);
|
||||
}
|
||||
break;
|
||||
case TFTP_EVENT_ERROR:
|
||||
|
||||
@@ -209,6 +209,20 @@ timediff_t Curl_timediff(struct curltime newer, struct curltime older)
|
||||
return diff * 1000 + (newer.tv_usec-older.tv_usec)/1000;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns: time difference in number of milliseconds, rounded up.
|
||||
* For too large diffs it returns max value.
|
||||
*/
|
||||
timediff_t Curl_timediff_ceil(struct curltime newer, struct curltime older)
|
||||
{
|
||||
timediff_t diff = (timediff_t)newer.tv_sec-older.tv_sec;
|
||||
if(diff >= (TIMEDIFF_T_MAX/1000))
|
||||
return TIMEDIFF_T_MAX;
|
||||
else if(diff <= (TIMEDIFF_T_MIN/1000))
|
||||
return TIMEDIFF_T_MIN;
|
||||
return diff * 1000 + (newer.tv_usec - older.tv_usec + 999)/1000;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns: time difference in number of microseconds. For too large diffs it
|
||||
* returns max value.
|
||||
|
||||
@@ -36,16 +36,24 @@ struct curltime {
|
||||
struct curltime Curl_now(void);
|
||||
|
||||
/*
|
||||
* Make sure that the first argument (t1) is the more recent time and t2 is
|
||||
* the older time, as otherwise you get a weird negative time-diff back...
|
||||
* Make sure that the first argument (newer) is the more recent time and older
|
||||
* is the older time, as otherwise you get a weird negative time-diff back...
|
||||
*
|
||||
* Returns: the time difference in number of milliseconds.
|
||||
*/
|
||||
timediff_t Curl_timediff(struct curltime t1, struct curltime t2);
|
||||
timediff_t Curl_timediff(struct curltime newer, struct curltime older);
|
||||
|
||||
/*
|
||||
* Make sure that the first argument (t1) is the more recent time and t2 is
|
||||
* the older time, as otherwise you get a weird negative time-diff back...
|
||||
* Make sure that the first argument (newer) is the more recent time and older
|
||||
* is the older time, as otherwise you get a weird negative time-diff back...
|
||||
*
|
||||
* Returns: the time difference in number of milliseconds, rounded up.
|
||||
*/
|
||||
timediff_t Curl_timediff_ceil(struct curltime newer, struct curltime older);
|
||||
|
||||
/*
|
||||
* Make sure that the first argument (newer) is the more recent time and older
|
||||
* is the older time, as otherwise you get a weird negative time-diff back...
|
||||
*
|
||||
* Returns: the time difference in number of microseconds.
|
||||
*/
|
||||
|
||||
@@ -40,9 +40,7 @@
|
||||
#ifdef HAVE_SYS_IOCTL_H
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
@@ -671,7 +669,9 @@ static CURLcode readwrite_data(struct Curl_easy *data,
|
||||
k->bytecount += nread;
|
||||
max_recv -= nread;
|
||||
|
||||
Curl_pgrsSetDownloadCounter(data, k->bytecount);
|
||||
result = Curl_pgrsSetDownloadCounter(data, k->bytecount);
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
if(!k->chunk && (nread || k->badheader || is_empty_data)) {
|
||||
/* If this is chunky transfer, it was already written */
|
||||
@@ -700,19 +700,15 @@ static CURLcode readwrite_data(struct Curl_easy *data,
|
||||
in http_chunks.c.
|
||||
Make sure that ALL_CONTENT_ENCODINGS contains all the
|
||||
encodings handled here. */
|
||||
if(data->set.http_ce_skip || !k->writer_stack) {
|
||||
if(!k->ignorebody && nread) {
|
||||
if(!k->ignorebody && nread) {
|
||||
#ifndef CURL_DISABLE_POP3
|
||||
if(conn->handler->protocol & PROTO_FAMILY_POP3)
|
||||
result = Curl_pop3_write(data, k->str, nread);
|
||||
else
|
||||
if(conn->handler->protocol & PROTO_FAMILY_POP3)
|
||||
result = Curl_pop3_write(data, k->str, nread);
|
||||
else
|
||||
#endif /* CURL_DISABLE_POP3 */
|
||||
result = Curl_client_write(data, CLIENTWRITE_BODY, k->str,
|
||||
nread);
|
||||
}
|
||||
result = Curl_client_write(data, CLIENTWRITE_BODY, k->str,
|
||||
nread);
|
||||
}
|
||||
else if(!k->ignorebody && nread)
|
||||
result = Curl_unencode_write(data, k->writer_stack, k->str, nread);
|
||||
}
|
||||
k->badheader = HEADER_NORMAL; /* taken care of now */
|
||||
|
||||
@@ -1050,6 +1046,19 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static int select_bits_paused(struct Curl_easy *data, int select_bits)
|
||||
{
|
||||
/* See issue #11982: we really need to be careful not to progress
|
||||
* a transfer direction when that direction is paused. Not all parts
|
||||
* of our state machine are handling PAUSED transfers correctly. So, we
|
||||
* do not want to go there.
|
||||
* NOTE: we are only interested in PAUSE, not HOLD. */
|
||||
return (((select_bits & CURL_CSELECT_IN) &&
|
||||
(data->req.keepon & KEEP_RECV_PAUSE)) ||
|
||||
((select_bits & CURL_CSELECT_OUT) &&
|
||||
(data->req.keepon & KEEP_SEND_PAUSE)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_readwrite() is the low-level function to be called when data is to
|
||||
* be read and written to/from the connection.
|
||||
@@ -1068,12 +1077,20 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
||||
int didwhat = 0;
|
||||
int select_bits;
|
||||
|
||||
|
||||
if(data->state.dselect_bits) {
|
||||
if(select_bits_paused(data, data->state.dselect_bits)) {
|
||||
/* leave the bits unchanged, so they'll tell us what to do when
|
||||
* this transfer gets unpaused. */
|
||||
DEBUGF(infof(data, "readwrite, dselect_bits, early return on PAUSED"));
|
||||
result = CURLE_OK;
|
||||
goto out;
|
||||
}
|
||||
select_bits = data->state.dselect_bits;
|
||||
data->state.dselect_bits = 0;
|
||||
}
|
||||
else if(conn->cselect_bits) {
|
||||
/* CAVEAT: adding `select_bits_paused()` check here makes test640 hang
|
||||
* (among others). Which hints at strange state handling in FTP land... */
|
||||
select_bits = conn->cselect_bits;
|
||||
conn->cselect_bits = 0;
|
||||
}
|
||||
|
||||
+35
-22
@@ -888,8 +888,8 @@ static bool conn_maxage(struct Curl_easy *data,
|
||||
idletime /= 1000; /* integer seconds is fine */
|
||||
|
||||
if(idletime > data->set.maxage_conn) {
|
||||
infof(data, "Too old connection (%ld seconds idle), disconnect it",
|
||||
idletime);
|
||||
infof(data, "Too old connection (%" CURL_FORMAT_TIMEDIFF_T
|
||||
" seconds idle), disconnect it", idletime);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -898,8 +898,8 @@ static bool conn_maxage(struct Curl_easy *data,
|
||||
|
||||
if(data->set.maxlifetime_conn && lifetime > data->set.maxlifetime_conn) {
|
||||
infof(data,
|
||||
"Too old connection (%ld seconds since creation), disconnect it",
|
||||
lifetime);
|
||||
"Too old connection (%" CURL_FORMAT_TIMEDIFF_T
|
||||
" seconds since creation), disconnect it", lifetime);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -1169,7 +1169,7 @@ ConnectionExists(struct Curl_easy *data,
|
||||
foundPendingCandidate = TRUE;
|
||||
/* Don't pick a connection that hasn't connected yet */
|
||||
infof(data, "Connection #%" CURL_FORMAT_CURL_OFF_T
|
||||
"isn't open enough, can't reuse", check->connection_id);
|
||||
" isn't open enough, can't reuse", check->connection_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2033,13 +2033,13 @@ void Curl_free_request_state(struct Curl_easy *data)
|
||||
{
|
||||
Curl_safefree(data->req.p.http);
|
||||
Curl_safefree(data->req.newurl);
|
||||
|
||||
#ifndef CURL_DISABLE_DOH
|
||||
if(data->req.doh) {
|
||||
Curl_close(&data->req.doh->probe[0].easy);
|
||||
Curl_close(&data->req.doh->probe[1].easy);
|
||||
}
|
||||
#endif
|
||||
Curl_client_cleanup(data);
|
||||
}
|
||||
|
||||
|
||||
@@ -2076,7 +2076,6 @@ static char *detect_proxy(struct Curl_easy *data,
|
||||
char proxy_env[128];
|
||||
const char *protop = conn->handler->scheme;
|
||||
char *envp = proxy_env;
|
||||
char *prox;
|
||||
#ifdef CURL_DISABLE_VERBOSE_STRINGS
|
||||
(void)data;
|
||||
#endif
|
||||
@@ -2089,7 +2088,7 @@ static char *detect_proxy(struct Curl_easy *data,
|
||||
strcpy(envp, "_proxy");
|
||||
|
||||
/* read the protocol proxy: */
|
||||
prox = curl_getenv(proxy_env);
|
||||
proxy = curl_getenv(proxy_env);
|
||||
|
||||
/*
|
||||
* We don't try the uppercase version of HTTP_PROXY because of
|
||||
@@ -2103,23 +2102,35 @@ static char *detect_proxy(struct Curl_easy *data,
|
||||
* This can cause 'internal' http/ftp requests to be
|
||||
* arbitrarily redirected by any external attacker.
|
||||
*/
|
||||
if(!prox && !strcasecompare("http_proxy", proxy_env)) {
|
||||
if(!proxy && !strcasecompare("http_proxy", proxy_env)) {
|
||||
/* There was no lowercase variable, try the uppercase version: */
|
||||
Curl_strntoupper(proxy_env, proxy_env, sizeof(proxy_env));
|
||||
prox = curl_getenv(proxy_env);
|
||||
proxy = curl_getenv(proxy_env);
|
||||
}
|
||||
|
||||
envp = proxy_env;
|
||||
if(prox) {
|
||||
proxy = prox; /* use this */
|
||||
}
|
||||
else {
|
||||
envp = (char *)"all_proxy";
|
||||
proxy = curl_getenv(envp); /* default proxy to use */
|
||||
if(!proxy) {
|
||||
envp = (char *)"ALL_PROXY";
|
||||
proxy = curl_getenv(envp);
|
||||
if(!proxy) {
|
||||
#ifdef USE_WEBSOCKETS
|
||||
/* websocket proxy fallbacks */
|
||||
if(strcasecompare("ws_proxy", proxy_env)) {
|
||||
proxy = curl_getenv("http_proxy");
|
||||
}
|
||||
else if(strcasecompare("wss_proxy", proxy_env)) {
|
||||
proxy = curl_getenv("https_proxy");
|
||||
if(!proxy)
|
||||
proxy = curl_getenv("HTTPS_PROXY");
|
||||
}
|
||||
if(!proxy) {
|
||||
#endif
|
||||
envp = (char *)"all_proxy";
|
||||
proxy = curl_getenv(envp); /* default proxy to use */
|
||||
if(!proxy) {
|
||||
envp = (char *)"ALL_PROXY";
|
||||
proxy = curl_getenv(envp);
|
||||
}
|
||||
#ifdef USE_WEBSOCKETS
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if(proxy)
|
||||
infof(data, "Uses proxy env variable %s == '%s'", envp, proxy);
|
||||
@@ -2719,7 +2730,9 @@ static CURLcode override_login(struct Curl_easy *data,
|
||||
data->set.str[STRING_NETRC_FILE]);
|
||||
if(ret > 0) {
|
||||
infof(data, "Couldn't find host %s in the %s file; using defaults",
|
||||
conn->host.name, data->set.str[STRING_NETRC_FILE]);
|
||||
conn->host.name,
|
||||
(data->set.str[STRING_NETRC_FILE] ?
|
||||
data->set.str[STRING_NETRC_FILE] : ".netrc"));
|
||||
}
|
||||
else if(ret < 0) {
|
||||
failf(data, ".netrc parser error");
|
||||
@@ -3214,8 +3227,8 @@ static CURLcode resolve_host(struct Curl_easy *data,
|
||||
if(rc == CURLRESOLV_PENDING)
|
||||
*async = TRUE;
|
||||
else if(rc == CURLRESOLV_TIMEDOUT) {
|
||||
failf(data, "Failed to resolve host '%s' with timeout after %ld ms",
|
||||
connhost->dispname,
|
||||
failf(data, "Failed to resolve host '%s' with timeout after %"
|
||||
CURL_FORMAT_TIMEDIFF_T " ms", connhost->dispname,
|
||||
Curl_timediff(Curl_now(), data->progress.t_startsingle));
|
||||
return CURLE_OPERATION_TIMEDOUT;
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ static void free_urlhandle(struct Curl_URL *u)
|
||||
|
||||
/*
|
||||
* Find the separator at the end of the host name, or the '?' in cases like
|
||||
* http://www.url.com?id=2380
|
||||
* http://www.example.com?id=2380
|
||||
*/
|
||||
static const char *find_host_sep(const char *url)
|
||||
{
|
||||
@@ -338,7 +338,7 @@ static char *concat_url(char *base, const char *relurl)
|
||||
pathsep = strchr(protsep, '/');
|
||||
if(pathsep) {
|
||||
/* When people use badly formatted URLs, such as
|
||||
"http://www.url.com?dir=/home/daniel" we must not use the first
|
||||
"http://www.example.com?dir=/home/daniel" we must not use the first
|
||||
slash, if there's a ?-letter before it! */
|
||||
char *sep = strchr(protsep, '?');
|
||||
if(sep && (sep < pathsep))
|
||||
@@ -347,9 +347,9 @@ static char *concat_url(char *base, const char *relurl)
|
||||
}
|
||||
else {
|
||||
/* There was no slash. Now, since we might be operating on a badly
|
||||
formatted URL, such as "http://www.url.com?id=2380" which doesn't
|
||||
use a slash separator as it is supposed to, we need to check for a
|
||||
?-letter as well! */
|
||||
formatted URL, such as "http://www.example.com?id=2380" which
|
||||
doesn't use a slash separator as it is supposed to, we need to check
|
||||
for a ?-letter as well! */
|
||||
pathsep = strchr(protsep, '?');
|
||||
if(pathsep)
|
||||
*pathsep = 0;
|
||||
@@ -1865,7 +1865,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
|
||||
if(result)
|
||||
return CURLUE_OUT_OF_MEMORY;
|
||||
}
|
||||
else if(Curl_isunreserved(*i) ||
|
||||
else if(ISUNRESERVED(*i) ||
|
||||
((*i == '/') && urlskipslash) ||
|
||||
((*i == '=') && equalsencode)) {
|
||||
if((*i == '=') && equalsencode)
|
||||
|
||||
@@ -640,7 +640,9 @@ struct SingleRequest {
|
||||
curl_off_t pendingheader; /* this many bytes left to send is actually
|
||||
header and not body */
|
||||
struct curltime start; /* transfer started at this time */
|
||||
unsigned int headerbytecount; /* only count received headers */
|
||||
unsigned int headerbytecount; /* received server headers (not CONNECT
|
||||
headers) */
|
||||
unsigned int allheadercount; /* all received headers (server + CONNECT) */
|
||||
unsigned int deductheadercount; /* this amount of bytes doesn't count when
|
||||
we check if anything has been transferred
|
||||
at the end of a connection. We use this
|
||||
@@ -1260,6 +1262,7 @@ struct tempbuf {
|
||||
struct dynbuf b;
|
||||
int type; /* type of the 'tempwrite' buffer as a bitmask that is used with
|
||||
Curl_client_write() */
|
||||
BIT(paused_body); /* if PAUSE happened before/during BODY write */
|
||||
};
|
||||
|
||||
/* Timers */
|
||||
@@ -1947,7 +1950,7 @@ struct Curl_easy {
|
||||
other using the same cache. For easier tracking
|
||||
in log output.
|
||||
This may wrap around after LONG_MAX to 0 again, so it
|
||||
has no uniqueness guarantuee for very large processings. */
|
||||
has no uniqueness guarantee for very large processings. */
|
||||
curl_off_t id;
|
||||
|
||||
/* first, two fields for the linked list of these */
|
||||
@@ -2010,6 +2013,10 @@ struct Curl_easy {
|
||||
#ifdef USE_HYPER
|
||||
struct hyptransfer hyp;
|
||||
#endif
|
||||
|
||||
/* internal: true if this easy handle was created for internal use and the
|
||||
user does not have ownership of the handle. */
|
||||
bool internal;
|
||||
};
|
||||
|
||||
#define LIBCURL_NAME "libcurl"
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
#include "urldata.h"
|
||||
|
||||
#include "vauth/vauth.h"
|
||||
#include "curl_md5.h"
|
||||
#include "warnless.h"
|
||||
#include "strtok.h"
|
||||
#include "sendf.h"
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
#ifdef USE_OPENSSL
|
||||
#include <openssl/err.h>
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
|
||||
#include <ngtcp2/ngtcp2_crypto_boringssl.h>
|
||||
#else
|
||||
#include <ngtcp2/ngtcp2_crypto_quictls.h>
|
||||
@@ -407,7 +407,7 @@ static CURLcode quic_ssl_ctx(SSL_CTX **pssl_ctx,
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
|
||||
if(ngtcp2_crypto_boringssl_configure_client_context(ssl_ctx) != 0) {
|
||||
failf(data, "ngtcp2_crypto_boringssl_configure_client_context failed");
|
||||
goto out;
|
||||
@@ -421,22 +421,24 @@ static CURLcode quic_ssl_ctx(SSL_CTX **pssl_ctx,
|
||||
|
||||
SSL_CTX_set_default_verify_paths(ssl_ctx);
|
||||
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
if(SSL_CTX_set1_curves_list(ssl_ctx, QUIC_GROUPS) != 1) {
|
||||
failf(data, "SSL_CTX_set1_curves_list failed");
|
||||
goto out;
|
||||
}
|
||||
#else
|
||||
if(SSL_CTX_set_ciphersuites(ssl_ctx, QUIC_CIPHERS) != 1) {
|
||||
char error_buffer[256];
|
||||
ERR_error_string_n(ERR_get_error(), error_buffer, sizeof(error_buffer));
|
||||
failf(data, "SSL_CTX_set_ciphersuites: %s", error_buffer);
|
||||
goto out;
|
||||
{
|
||||
const char *curves = conn->ssl_config.curves ?
|
||||
conn->ssl_config.curves : QUIC_GROUPS;
|
||||
if(!SSL_CTX_set1_curves_list(ssl_ctx, curves)) {
|
||||
failf(data, "failed setting curves list for QUIC: '%s'", curves);
|
||||
return CURLE_SSL_CIPHER;
|
||||
}
|
||||
}
|
||||
|
||||
if(SSL_CTX_set1_groups_list(ssl_ctx, QUIC_GROUPS) != 1) {
|
||||
failf(data, "SSL_CTX_set1_groups_list failed");
|
||||
goto out;
|
||||
#ifndef OPENSSL_IS_BORINGSSL
|
||||
{
|
||||
const char *ciphers13 = conn->ssl_config.cipher_list13 ?
|
||||
conn->ssl_config.cipher_list13 : QUIC_CIPHERS;
|
||||
if(SSL_CTX_set_ciphersuites(ssl_ctx, ciphers13) != 1) {
|
||||
failf(data, "failed setting QUIC cipher suite: %s", ciphers13);
|
||||
return CURLE_SSL_CIPHER;
|
||||
}
|
||||
infof(data, "QUIC cipher selection: %s", ciphers13);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -616,15 +618,19 @@ static CURLcode quic_ssl_ctx(WOLFSSL_CTX **pssl_ctx,
|
||||
|
||||
wolfSSL_CTX_set_default_verify_paths(ssl_ctx);
|
||||
|
||||
if(wolfSSL_CTX_set_cipher_list(ssl_ctx, QUIC_CIPHERS) != 1) {
|
||||
if(wolfSSL_CTX_set_cipher_list(ssl_ctx, conn->ssl_config.cipher_list13 ?
|
||||
conn->ssl_config.cipher_list13 :
|
||||
QUIC_CIPHERS) != 1) {
|
||||
char error_buffer[256];
|
||||
ERR_error_string_n(ERR_get_error(), error_buffer, sizeof(error_buffer));
|
||||
failf(data, "wolfSSL_CTX_set_cipher_list: %s", error_buffer);
|
||||
failf(data, "wolfSSL failed to set ciphers: %s", error_buffer);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(wolfSSL_CTX_set1_groups_list(ssl_ctx, (char *)QUIC_GROUPS) != 1) {
|
||||
failf(data, "SSL_CTX_set1_groups_list failed");
|
||||
if(wolfSSL_CTX_set1_groups_list(ssl_ctx, conn->ssl_config.curves ?
|
||||
conn->ssl_config.curves :
|
||||
(char *)QUIC_GROUPS) != 1) {
|
||||
failf(data, "wolfSSL failed to set curves");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -644,10 +650,13 @@ static CURLcode quic_ssl_ctx(WOLFSSL_CTX **pssl_ctx,
|
||||
const char * const ssl_capath = conn->ssl_config.CApath;
|
||||
|
||||
wolfSSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
|
||||
if(conn->ssl_config.CAfile || conn->ssl_config.CApath) {
|
||||
if(ssl_cafile || ssl_capath) {
|
||||
/* tell wolfSSL where to find CA certificates that are used to verify
|
||||
the server's certificate. */
|
||||
if(!wolfSSL_CTX_load_verify_locations(ssl_ctx, ssl_cafile, ssl_capath)) {
|
||||
int rc =
|
||||
wolfSSL_CTX_load_verify_locations_ex(ssl_ctx, ssl_cafile, ssl_capath,
|
||||
WOLFSSL_LOAD_FLAG_IGNORE_ERR);
|
||||
if(SSL_SUCCESS != rc) {
|
||||
/* Fail if we insist on successfully verifying the server. */
|
||||
failf(data, "error setting certificate verify locations:"
|
||||
" CAfile: %s CApath: %s",
|
||||
|
||||
@@ -149,8 +149,8 @@ static CURLcode quic_x509_store_setup(struct Curl_cfilter *cf,
|
||||
SSL_CTX_set_verify(ctx->sslctx, SSL_VERIFY_PEER, NULL);
|
||||
/* tell OpenSSL where to find CA certificates that are used to verify
|
||||
the server's certificate. */
|
||||
if(!SSL_CTX_load_verify_locations(
|
||||
ctx->sslctx, ssl_cafile, ssl_capath)) {
|
||||
if(!SSL_CTX_load_verify_locations(ctx->sslctx, ssl_cafile,
|
||||
ssl_capath)) {
|
||||
/* Fail if we insist on successfully verifying the server. */
|
||||
failf(data, "error setting certificate verify locations:"
|
||||
" CAfile: %s CApath: %s",
|
||||
@@ -165,7 +165,7 @@ static CURLcode quic_x509_store_setup(struct Curl_cfilter *cf,
|
||||
else {
|
||||
/* verifying the peer without any CA certificates won't work so
|
||||
use openssl's built-in default as fallback */
|
||||
SSL_CTX_set_default_verify_paths(ssl_ctx);
|
||||
SSL_CTX_set_default_verify_paths(ctx->sslctx);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -178,6 +178,8 @@ static CURLcode quic_ssl_setup(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
{
|
||||
struct cf_quiche_ctx *ctx = cf->ctx;
|
||||
unsigned char checkip[16];
|
||||
struct connectdata *conn = data->conn;
|
||||
const char *curves = conn->ssl_config.curves;
|
||||
|
||||
DEBUGASSERT(!ctx->sslctx);
|
||||
ctx->sslctx = SSL_CTX_new(TLS_method());
|
||||
@@ -196,6 +198,11 @@ static CURLcode quic_ssl_setup(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
SSL_CTX_set_keylog_callback(ctx->sslctx, keylog_callback);
|
||||
}
|
||||
|
||||
if(curves && !SSL_CTX_set1_curves_list(ctx->sslctx, curves)) {
|
||||
failf(data, "failed setting curves list for QUIC: '%s'", curves);
|
||||
return CURLE_SSL_CIPHER;
|
||||
}
|
||||
|
||||
ctx->ssl = SSL_new(ctx->sslctx);
|
||||
if(!ctx->ssl)
|
||||
return CURLE_QUIC_CONNECT_ERROR;
|
||||
|
||||
@@ -2567,6 +2567,12 @@ static ssize_t sftp_send(struct Curl_easy *data, int sockindex,
|
||||
struct connectdata *conn = data->conn;
|
||||
(void)sockindex;
|
||||
|
||||
/* limit the writes to the maximum specified in Section 3 of
|
||||
* https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-02
|
||||
*/
|
||||
if(len > 32768)
|
||||
len = 32768;
|
||||
|
||||
nwrite = sftp_write(conn->proto.sshc.sftp_file, mem, len);
|
||||
|
||||
myssh_block2waitfor(conn, FALSE);
|
||||
@@ -2654,7 +2660,7 @@ static void sftp_quote(struct Curl_easy *data)
|
||||
/* if a command starts with an asterisk, which a legal SFTP command never
|
||||
can, the command will be allowed to fail without it causing any
|
||||
aborts or cancels etc. It will cause libcurl to act as if the command
|
||||
is successful, whatever the server reponds. */
|
||||
is successful, whatever the server responds. */
|
||||
|
||||
if(cmd[0] == '*') {
|
||||
cmd++;
|
||||
@@ -2828,7 +2834,7 @@ static void sftp_quote_stat(struct Curl_easy *data)
|
||||
/* if a command starts with an asterisk, which a legal SFTP command never
|
||||
can, the command will be allowed to fail without it causing any
|
||||
aborts or cancels etc. It will cause libcurl to act as if the command
|
||||
is successful, whatever the server reponds. */
|
||||
is successful, whatever the server responds. */
|
||||
|
||||
if(cmd[0] == '*') {
|
||||
cmd++;
|
||||
|
||||
@@ -1178,8 +1178,16 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
|
||||
}
|
||||
else {
|
||||
char *err_msg = NULL;
|
||||
(void)libssh2_session_last_error(sshc->ssh_session,
|
||||
&err_msg, NULL, 0);
|
||||
char unknown[] = "Reason unknown (-1)";
|
||||
if(rc == -1) {
|
||||
/* No error message has been set and the last set error message, if
|
||||
any, is from a previous error so ignore it. #11837 */
|
||||
err_msg = unknown;
|
||||
}
|
||||
else {
|
||||
(void)libssh2_session_last_error(sshc->ssh_session,
|
||||
&err_msg, NULL, 0);
|
||||
}
|
||||
infof(data, "SSH public key authentication failed: %s", err_msg);
|
||||
state(data, SSH_AUTH_PASS_INIT);
|
||||
rc = 0; /* clear rc and continue */
|
||||
@@ -1495,7 +1503,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
|
||||
/* if a command starts with an asterisk, which a legal SFTP command never
|
||||
can, the command will be allowed to fail without it causing any
|
||||
aborts or cancels etc. It will cause libcurl to act as if the command
|
||||
is successful, whatever the server reponds. */
|
||||
is successful, whatever the server responds. */
|
||||
|
||||
if(cmd[0] == '*') {
|
||||
cmd++;
|
||||
@@ -1691,7 +1699,7 @@ static CURLcode ssh_statemach_act(struct Curl_easy *data, bool *block)
|
||||
/* if a command starts with an asterisk, which a legal SFTP command never
|
||||
can, the command will be allowed to fail without it causing any
|
||||
aborts or cancels etc. It will cause libcurl to act as if the command
|
||||
is successful, whatever the server reponds. */
|
||||
is successful, whatever the server responds. */
|
||||
|
||||
if(cmd[0] == '*') {
|
||||
cmd++;
|
||||
|
||||
@@ -1168,6 +1168,7 @@ CURLcode Curl_ssh_init(void)
|
||||
}
|
||||
void Curl_ssh_cleanup(void)
|
||||
{
|
||||
(void)wolfSSH_Cleanup();
|
||||
}
|
||||
|
||||
#endif /* USE_WOLFSSH */
|
||||
|
||||
@@ -1473,7 +1473,6 @@ static int gtls_shutdown(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
struct ssl_connect_data *connssl = cf->ctx;
|
||||
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
|
||||
struct gtls_ssl_backend_data *backend =
|
||||
(struct gtls_ssl_backend_data *)connssl->backend;
|
||||
int retval = 0;
|
||||
@@ -1536,8 +1535,11 @@ static int gtls_shutdown(struct Curl_cfilter *cf,
|
||||
gnutls_certificate_free_credentials(backend->gtls.cred);
|
||||
|
||||
#ifdef USE_GNUTLS_SRP
|
||||
if(ssl_config->primary.username)
|
||||
gnutls_srp_free_client_credentials(backend->gtls.srp_client_cred);
|
||||
{
|
||||
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
|
||||
if(ssl_config->primary.username)
|
||||
gnutls_srp_free_client_credentials(backend->gtls.srp_client_cred);
|
||||
}
|
||||
#endif
|
||||
|
||||
backend->gtls.cred = NULL;
|
||||
|
||||
@@ -156,7 +156,8 @@ static void mbed_debug(void *context, int level, const char *f_name,
|
||||
#else
|
||||
#endif
|
||||
|
||||
static int bio_cf_write(void *bio, const unsigned char *buf, size_t blen)
|
||||
static int mbedtls_bio_cf_write(void *bio,
|
||||
const unsigned char *buf, size_t blen)
|
||||
{
|
||||
struct Curl_cfilter *cf = bio;
|
||||
struct Curl_easy *data = CF_DATA_CURRENT(cf);
|
||||
@@ -165,7 +166,7 @@ static int bio_cf_write(void *bio, const unsigned char *buf, size_t blen)
|
||||
|
||||
DEBUGASSERT(data);
|
||||
nwritten = Curl_conn_cf_send(cf->next, data, (char *)buf, blen, &result);
|
||||
CURL_TRC_CF(data, cf, "bio_cf_out_write(len=%zu) -> %zd, err=%d",
|
||||
CURL_TRC_CF(data, cf, "mbedtls_bio_cf_out_write(len=%zu) -> %zd, err=%d",
|
||||
blen, nwritten, result);
|
||||
if(nwritten < 0 && CURLE_AGAIN == result) {
|
||||
nwritten = MBEDTLS_ERR_SSL_WANT_WRITE;
|
||||
@@ -173,7 +174,7 @@ static int bio_cf_write(void *bio, const unsigned char *buf, size_t blen)
|
||||
return (int)nwritten;
|
||||
}
|
||||
|
||||
static int bio_cf_read(void *bio, unsigned char *buf, size_t blen)
|
||||
static int mbedtls_bio_cf_read(void *bio, unsigned char *buf, size_t blen)
|
||||
{
|
||||
struct Curl_cfilter *cf = bio;
|
||||
struct Curl_easy *data = CF_DATA_CURRENT(cf);
|
||||
@@ -186,7 +187,7 @@ static int bio_cf_read(void *bio, unsigned char *buf, size_t blen)
|
||||
return 0;
|
||||
|
||||
nread = Curl_conn_cf_recv(cf->next, data, (char *)buf, blen, &result);
|
||||
CURL_TRC_CF(data, cf, "bio_cf_in_read(len=%zu) -> %zd, err=%d",
|
||||
CURL_TRC_CF(data, cf, "mbedtls_bio_cf_in_read(len=%zu) -> %zd, err=%d",
|
||||
blen, nread, result);
|
||||
if(nread < 0 && CURLE_AGAIN == result) {
|
||||
nread = MBEDTLS_ERR_SSL_WANT_READ;
|
||||
@@ -591,7 +592,9 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
|
||||
mbedtls_ssl_conf_rng(&backend->config, mbedtls_ctr_drbg_random,
|
||||
&backend->ctr_drbg);
|
||||
mbedtls_ssl_set_bio(&backend->ssl, cf, bio_cf_write, bio_cf_read,
|
||||
mbedtls_ssl_set_bio(&backend->ssl, cf,
|
||||
mbedtls_bio_cf_write,
|
||||
mbedtls_bio_cf_read,
|
||||
NULL /* rev_timeout() */);
|
||||
|
||||
mbedtls_ssl_conf_ciphersuites(&backend->config,
|
||||
|
||||
@@ -474,7 +474,9 @@ CURLcode Curl_ossl_certchain(struct Curl_easy *data, SSL *ssl)
|
||||
|
||||
X509_get0_signature(&psig, &sigalg, x);
|
||||
if(sigalg) {
|
||||
i2a_ASN1_OBJECT(mem, sigalg->algorithm);
|
||||
const ASN1_OBJECT *sigalgoid = NULL;
|
||||
X509_ALGOR_get0(&sigalgoid, NULL, NULL, sigalg);
|
||||
i2a_ASN1_OBJECT(mem, sigalgoid);
|
||||
push_certinfo("Signature Algorithm", i);
|
||||
}
|
||||
|
||||
@@ -669,7 +671,7 @@ CURLcode Curl_ossl_certchain(struct Curl_easy *data, SSL *ssl)
|
||||
#define BIO_set_shutdown(x,v) ((x)->shutdown=(v))
|
||||
#endif /* USE_PRE_1_1_API */
|
||||
|
||||
static int bio_cf_create(BIO *bio)
|
||||
static int ossl_bio_cf_create(BIO *bio)
|
||||
{
|
||||
BIO_set_shutdown(bio, 1);
|
||||
BIO_set_init(bio, 1);
|
||||
@@ -680,14 +682,14 @@ static int bio_cf_create(BIO *bio)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int bio_cf_destroy(BIO *bio)
|
||||
static int ossl_bio_cf_destroy(BIO *bio)
|
||||
{
|
||||
if(!bio)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static long bio_cf_ctrl(BIO *bio, int cmd, long num, void *ptr)
|
||||
static long ossl_bio_cf_ctrl(BIO *bio, int cmd, long num, void *ptr)
|
||||
{
|
||||
struct Curl_cfilter *cf = BIO_get_data(bio);
|
||||
long ret = 1;
|
||||
@@ -721,7 +723,7 @@ static long bio_cf_ctrl(BIO *bio, int cmd, long num, void *ptr)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bio_cf_out_write(BIO *bio, const char *buf, int blen)
|
||||
static int ossl_bio_cf_out_write(BIO *bio, const char *buf, int blen)
|
||||
{
|
||||
struct Curl_cfilter *cf = BIO_get_data(bio);
|
||||
struct ssl_connect_data *connssl = cf->ctx;
|
||||
@@ -733,7 +735,7 @@ static int bio_cf_out_write(BIO *bio, const char *buf, int blen)
|
||||
|
||||
DEBUGASSERT(data);
|
||||
nwritten = Curl_conn_cf_send(cf->next, data, buf, blen, &result);
|
||||
CURL_TRC_CF(data, cf, "bio_cf_out_write(len=%d) -> %d, err=%d",
|
||||
CURL_TRC_CF(data, cf, "ossl_bio_cf_out_write(len=%d) -> %d, err=%d",
|
||||
blen, (int)nwritten, result);
|
||||
BIO_clear_retry_flags(bio);
|
||||
backend->io_result = result;
|
||||
@@ -744,7 +746,7 @@ static int bio_cf_out_write(BIO *bio, const char *buf, int blen)
|
||||
return (int)nwritten;
|
||||
}
|
||||
|
||||
static int bio_cf_in_read(BIO *bio, char *buf, int blen)
|
||||
static int ossl_bio_cf_in_read(BIO *bio, char *buf, int blen)
|
||||
{
|
||||
struct Curl_cfilter *cf = BIO_get_data(bio);
|
||||
struct ssl_connect_data *connssl = cf->ctx;
|
||||
@@ -760,7 +762,7 @@ static int bio_cf_in_read(BIO *bio, char *buf, int blen)
|
||||
return 0;
|
||||
|
||||
nread = Curl_conn_cf_recv(cf->next, data, buf, blen, &result);
|
||||
CURL_TRC_CF(data, cf, "bio_cf_in_read(len=%d) -> %d, err=%d",
|
||||
CURL_TRC_CF(data, cf, "ossl_bio_cf_in_read(len=%d) -> %d, err=%d",
|
||||
blen, (int)nread, result);
|
||||
BIO_clear_retry_flags(bio);
|
||||
backend->io_result = result;
|
||||
@@ -785,42 +787,42 @@ static int bio_cf_in_read(BIO *bio, char *buf, int blen)
|
||||
|
||||
#if USE_PRE_1_1_API
|
||||
|
||||
static BIO_METHOD bio_cf_meth_1_0 = {
|
||||
static BIO_METHOD ossl_bio_cf_meth_1_0 = {
|
||||
BIO_TYPE_MEM,
|
||||
"OpenSSL CF BIO",
|
||||
bio_cf_out_write,
|
||||
bio_cf_in_read,
|
||||
ossl_bio_cf_out_write,
|
||||
ossl_bio_cf_in_read,
|
||||
NULL, /* puts is never called */
|
||||
NULL, /* gets is never called */
|
||||
bio_cf_ctrl,
|
||||
bio_cf_create,
|
||||
bio_cf_destroy,
|
||||
ossl_bio_cf_ctrl,
|
||||
ossl_bio_cf_create,
|
||||
ossl_bio_cf_destroy,
|
||||
NULL
|
||||
};
|
||||
|
||||
static BIO_METHOD *bio_cf_method_create(void)
|
||||
static BIO_METHOD *ossl_bio_cf_method_create(void)
|
||||
{
|
||||
return &bio_cf_meth_1_0;
|
||||
return &ossl_bio_cf_meth_1_0;
|
||||
}
|
||||
|
||||
#define bio_cf_method_free(m) Curl_nop_stmt
|
||||
#define ossl_bio_cf_method_free(m) Curl_nop_stmt
|
||||
|
||||
#else
|
||||
|
||||
static BIO_METHOD *bio_cf_method_create(void)
|
||||
static BIO_METHOD *ossl_bio_cf_method_create(void)
|
||||
{
|
||||
BIO_METHOD *m = BIO_meth_new(BIO_TYPE_MEM, "OpenSSL CF BIO");
|
||||
if(m) {
|
||||
BIO_meth_set_write(m, &bio_cf_out_write);
|
||||
BIO_meth_set_read(m, &bio_cf_in_read);
|
||||
BIO_meth_set_ctrl(m, &bio_cf_ctrl);
|
||||
BIO_meth_set_create(m, &bio_cf_create);
|
||||
BIO_meth_set_destroy(m, &bio_cf_destroy);
|
||||
BIO_meth_set_write(m, &ossl_bio_cf_out_write);
|
||||
BIO_meth_set_read(m, &ossl_bio_cf_in_read);
|
||||
BIO_meth_set_ctrl(m, &ossl_bio_cf_ctrl);
|
||||
BIO_meth_set_create(m, &ossl_bio_cf_create);
|
||||
BIO_meth_set_destroy(m, &ossl_bio_cf_destroy);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
static void bio_cf_method_free(BIO_METHOD *m)
|
||||
static void ossl_bio_cf_method_free(BIO_METHOD *m)
|
||||
{
|
||||
if(m)
|
||||
BIO_meth_free(m);
|
||||
@@ -1559,11 +1561,9 @@ fail:
|
||||
UI_method_set_closer(ui_method, UI_method_get_closer(UI_OpenSSL()));
|
||||
UI_method_set_reader(ui_method, ssl_ui_reader);
|
||||
UI_method_set_writer(ui_method, ssl_ui_writer);
|
||||
/* the typecast below was added to please mingw32 */
|
||||
priv_key = (EVP_PKEY *)
|
||||
ENGINE_load_private_key(data->state.engine, key_file,
|
||||
ui_method,
|
||||
key_passwd);
|
||||
priv_key = ENGINE_load_private_key(data->state.engine, key_file,
|
||||
ui_method,
|
||||
key_passwd);
|
||||
UI_destroy_method(ui_method);
|
||||
if(!priv_key) {
|
||||
failf(data, "failed to load private key from crypto engine");
|
||||
@@ -1886,15 +1886,45 @@ static void ossl_close(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
|
||||
if(backend->handle) {
|
||||
if(cf->next && cf->next->connected) {
|
||||
char buf[32];
|
||||
char buf[1024];
|
||||
int nread, err;
|
||||
long sslerr;
|
||||
|
||||
/* Maybe the server has already sent a close notify alert.
|
||||
Read it to avoid an RST on the TCP connection. */
|
||||
(void)SSL_read(backend->handle, buf, (int)sizeof(buf));
|
||||
|
||||
(void)SSL_shutdown(backend->handle);
|
||||
ERR_clear_error();
|
||||
if(SSL_shutdown(backend->handle) == 1) {
|
||||
CURL_TRC_CF(data, cf, "SSL shutdown finished");
|
||||
}
|
||||
else {
|
||||
nread = SSL_read(backend->handle, buf, (int)sizeof(buf));
|
||||
err = SSL_get_error(backend->handle, nread);
|
||||
switch(err) {
|
||||
case SSL_ERROR_NONE: /* this is not an error */
|
||||
case SSL_ERROR_ZERO_RETURN: /* no more data */
|
||||
CURL_TRC_CF(data, cf, "SSL shutdown, EOF from server");
|
||||
break;
|
||||
case SSL_ERROR_WANT_READ:
|
||||
/* SSL has send its notify and now wants to read the reply
|
||||
* from the server. We are not really interested in that. */
|
||||
CURL_TRC_CF(data, cf, "SSL shutdown sent");
|
||||
break;
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
CURL_TRC_CF(data, cf, "SSL shutdown send blocked");
|
||||
break;
|
||||
default:
|
||||
sslerr = ERR_get_error();
|
||||
CURL_TRC_CF(data, cf, "SSL shutdown, error: '%s', errno %d",
|
||||
(sslerr ?
|
||||
ossl_strerror(sslerr, buf, sizeof(buf)) :
|
||||
SSL_ERROR_to_str(err)),
|
||||
SOCKERRNO);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ERR_clear_error();
|
||||
|
||||
SSL_set_connect_state(backend->handle);
|
||||
}
|
||||
|
||||
@@ -1907,7 +1937,7 @@ static void ossl_close(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
backend->x509_store_setup = FALSE;
|
||||
}
|
||||
if(backend->bio_method) {
|
||||
bio_cf_method_free(backend->bio_method);
|
||||
ossl_bio_cf_method_free(backend->bio_method);
|
||||
backend->bio_method = NULL;
|
||||
}
|
||||
}
|
||||
@@ -3805,7 +3835,7 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
|
||||
Curl_ssl_sessionid_unlock(data);
|
||||
}
|
||||
|
||||
backend->bio_method = bio_cf_method_create();
|
||||
backend->bio_method = ossl_bio_cf_method_create();
|
||||
if(!backend->bio_method)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
bio = BIO_new(backend->bio_method);
|
||||
|
||||
@@ -68,22 +68,6 @@
|
||||
# define HAS_ALPN 1
|
||||
#endif
|
||||
|
||||
#ifndef UNISP_NAME_A
|
||||
#define UNISP_NAME_A "Microsoft Unified Security Protocol Provider"
|
||||
#endif
|
||||
|
||||
#ifndef UNISP_NAME_W
|
||||
#define UNISP_NAME_W L"Microsoft Unified Security Protocol Provider"
|
||||
#endif
|
||||
|
||||
#ifndef UNISP_NAME
|
||||
#ifdef UNICODE
|
||||
#define UNISP_NAME UNISP_NAME_W
|
||||
#else
|
||||
#define UNISP_NAME UNISP_NAME_A
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef BCRYPT_CHACHA20_POLY1305_ALGORITHM
|
||||
#define BCRYPT_CHACHA20_POLY1305_ALGORITHM L"CHACHA20_POLY1305"
|
||||
#endif
|
||||
@@ -108,13 +92,6 @@
|
||||
#define BCRYPT_SHA384_ALGORITHM L"SHA384"
|
||||
#endif
|
||||
|
||||
/* Workaround broken compilers like MinGW.
|
||||
Return the number of elements in a statically sized array.
|
||||
*/
|
||||
#ifndef ARRAYSIZE
|
||||
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
|
||||
#endif
|
||||
|
||||
#ifdef HAS_CLIENT_CERT_PATH
|
||||
#ifdef UNICODE
|
||||
#define CURL_CERT_STORE_PROV_SYSTEM CERT_STORE_PROV_SYSTEM_W
|
||||
@@ -123,18 +100,6 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef SP_PROT_SSL2_CLIENT
|
||||
#define SP_PROT_SSL2_CLIENT 0x00000008
|
||||
#endif
|
||||
|
||||
#ifndef SP_PROT_SSL3_CLIENT
|
||||
#define SP_PROT_SSL3_CLIENT 0x00000008
|
||||
#endif
|
||||
|
||||
#ifndef SP_PROT_TLS1_CLIENT
|
||||
#define SP_PROT_TLS1_CLIENT 0x00000080
|
||||
#endif
|
||||
|
||||
#ifndef SP_PROT_TLS1_0_CLIENT
|
||||
#define SP_PROT_TLS1_0_CLIENT SP_PROT_TLS1_CLIENT
|
||||
#endif
|
||||
@@ -175,12 +140,6 @@
|
||||
# define CALG_SHA_256 0x0000800c
|
||||
#endif
|
||||
|
||||
/* Work around typo in classic MinGW's w32api up to version 5.0,
|
||||
see https://osdn.net/projects/mingw/ticket/38391 */
|
||||
#if !defined(ALG_CLASS_DHASH) && defined(ALG_CLASS_HASH)
|
||||
#define ALG_CLASS_DHASH ALG_CLASS_HASH
|
||||
#endif
|
||||
|
||||
#ifndef PKCS12_NO_PERSIST_KEY
|
||||
#define PKCS12_NO_PERSIST_KEY 0x00008000
|
||||
#endif
|
||||
@@ -769,7 +728,7 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf,
|
||||
}
|
||||
#endif
|
||||
|
||||
/* allocate memory for the re-usable credential handle */
|
||||
/* allocate memory for the reusable credential handle */
|
||||
backend->cred = (struct Curl_schannel_cred *)
|
||||
calloc(1, sizeof(struct Curl_schannel_cred));
|
||||
if(!backend->cred) {
|
||||
@@ -1169,7 +1128,7 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
|
||||
backend->cred = NULL;
|
||||
|
||||
/* check for an existing re-usable credential handle */
|
||||
/* check for an existing reusable credential handle */
|
||||
if(ssl_config->primary.sessionid) {
|
||||
Curl_ssl_sessionid_lock(data);
|
||||
if(!Curl_ssl_getsessionid(cf, data, (void **)&old_cred, NULL)) {
|
||||
@@ -2752,8 +2711,7 @@ static void schannel_checksum(const unsigned char *input,
|
||||
if(!CryptCreateHash(hProv, algId, 0, 0, &hHash))
|
||||
break; /* failed */
|
||||
|
||||
/* workaround for original MinGW, should be (const BYTE*) */
|
||||
if(!CryptHashData(hHash, (BYTE*)input, (DWORD)inputlen, 0))
|
||||
if(!CryptHashData(hHash, input, (DWORD)inputlen, 0))
|
||||
break; /* failed */
|
||||
|
||||
/* get hash size */
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
* BoringSSL's <openssl/x509.h>: So just undefine those defines here
|
||||
* (and only here).
|
||||
*/
|
||||
#if defined(HAVE_BORINGSSL) || defined(OPENSSL_IS_BORINGSSL)
|
||||
#if defined(OPENSSL_IS_BORINGSSL)
|
||||
# undef X509_NAME
|
||||
# undef X509_CERT_PAIR
|
||||
# undef X509_EXTENSIONS
|
||||
|
||||
@@ -28,15 +28,9 @@
|
||||
|
||||
#ifdef USE_SCHANNEL
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#ifdef __MINGW64_VERSION_MAJOR
|
||||
#if defined(__MINGW32__) || defined(CERT_CHAIN_REVOCATION_CHECK_CHAIN)
|
||||
#define HAS_MANUAL_VERIFY_API
|
||||
#endif
|
||||
#else
|
||||
#ifdef CERT_CHAIN_REVOCATION_CHECK_CHAIN
|
||||
#define HAS_MANUAL_VERIFY_API
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(CryptStringToBinary) && defined(CRYPT_STRING_HEX) \
|
||||
&& !defined(DISABLE_SCHANNEL_CLIENT_CERT)
|
||||
@@ -60,41 +54,6 @@
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
|
||||
/* Original mingw is missing CERT structs or they're disabled.
|
||||
Refer to w32api-5.0.2-mingw32-dev\include\wincrypt.h. */
|
||||
|
||||
/* !checksrc! disable TYPEDEFSTRUCT 4 */
|
||||
typedef struct _CERT_OTHER_NAME {
|
||||
LPSTR pszObjId;
|
||||
CRYPT_OBJID_BLOB Value;
|
||||
} CERT_OTHER_NAME, *PCERT_OTHER_NAME;
|
||||
|
||||
typedef struct _CERT_ALT_NAME_ENTRY {
|
||||
DWORD dwAltNameChoice;
|
||||
union {
|
||||
PCERT_OTHER_NAME pOtherName;
|
||||
LPWSTR pwszRfc822Name;
|
||||
LPWSTR pwszDNSName;
|
||||
CERT_NAME_BLOB DirectoryName;
|
||||
LPWSTR pwszURL;
|
||||
CRYPT_DATA_BLOB IPAddress;
|
||||
LPSTR pszRegisteredID;
|
||||
};
|
||||
} CERT_ALT_NAME_ENTRY, *PCERT_ALT_NAME_ENTRY;
|
||||
|
||||
typedef struct _CERT_ALT_NAME_INFO {
|
||||
DWORD cAltEntry;
|
||||
PCERT_ALT_NAME_ENTRY rgAltEntry;
|
||||
} CERT_ALT_NAME_INFO, *PCERT_ALT_NAME_INFO;
|
||||
|
||||
typedef struct _CRYPT_DECODE_PARA {
|
||||
DWORD cbSize;
|
||||
PFN_CRYPT_ALLOC pfnAlloc;
|
||||
PFN_CRYPT_FREE pfnFree;
|
||||
} CRYPT_DECODE_PARA, *PCRYPT_DECODE_PARA;
|
||||
#endif
|
||||
|
||||
#ifndef SCH_CREDENTIALS_VERSION
|
||||
|
||||
#define SCH_CREDENTIALS_VERSION 0x00000005
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user