mirror of
https://github.com/Kitware/CMake.git
synced 2026-05-06 06:10:04 -05:00
Merge branch 'upstream-curl' into update-curl
* upstream-curl:
curl 2023-09-13 (6fa1d817)
Upstream significantly refactored `lib/CMakeLists.txt`, so take the
upstream version of everything except the code added by commit
54cb23c657 (curl: Restore installation of OpenSSL DLLs, 2014-11-03,
v3.2.0-rc1~418^2~4). We will apply our customizations again in a
follow-up commit.
This commit is contained in:
@@ -510,7 +510,7 @@ main() {
|
||||
int
|
||||
main() {
|
||||
_Atomic int i = 1;
|
||||
i = 0; // Force an atomic-write operation.
|
||||
i = 0; /* Force an atomic-write operation. */
|
||||
return i;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
#***************************************************************************
|
||||
# _ _ ____ _
|
||||
# Project ___| | | | _ \| |
|
||||
# / __| | | | |_) | |
|
||||
# | (__| |_| | _ <| |___
|
||||
# \___|\___/|_| \_\_____|
|
||||
#
|
||||
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
#
|
||||
# This software is licensed as described in the file COPYING, which
|
||||
# you should have received as part of this distribution. The terms
|
||||
# are also available at https://curl.se/docs/copyright.html.
|
||||
#
|
||||
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
# copies of the Software, and permit persons to whom the Software is
|
||||
# furnished to do so, under the terms of the COPYING file.
|
||||
#
|
||||
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
# KIND, either express or implied.
|
||||
#
|
||||
# SPDX-License-Identifier: curl
|
||||
#
|
||||
###########################################################################
|
||||
if(UNIX)
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_search_module(PC_NSS nss)
|
||||
endif()
|
||||
if(NOT PC_NSS_FOUND)
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(NSS_LIBRARIES ${PC_NSS_LINK_LIBRARIES})
|
||||
set(NSS_INCLUDE_DIRS ${PC_NSS_INCLUDE_DIRS})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(NSS
|
||||
REQUIRED_VARS NSS_LIBRARIES NSS_INCLUDE_DIRS
|
||||
VERSION_VAR PC_NSS_VERSION)
|
||||
|
||||
mark_as_advanced(NSS_INCLUDE_DIRS NSS_LIBRARIES)
|
||||
@@ -38,7 +38,7 @@ if(HAVE_WINDOWS_H)
|
||||
set(_source_epilogue
|
||||
"${_source_epilogue}\n#ifndef WIN32_LEAN_AND_MEAN\n#define WIN32_LEAN_AND_MEAN\n#endif")
|
||||
set(signature_call_conv "PASCAL")
|
||||
if(HAVE_LIBWS2_32)
|
||||
if(WIN32)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ws2_32)
|
||||
endif()
|
||||
else()
|
||||
@@ -133,4 +133,3 @@ if(NOT CMAKE_CROSSCOMPILING)
|
||||
}" HAVE_POLL_FINE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
@@ -23,30 +23,64 @@
|
||||
###########################################################################
|
||||
if(NOT UNIX)
|
||||
if(WIN32)
|
||||
|
||||
set(HAVE_WINDOWS_H 1)
|
||||
set(HAVE_WS2TCPIP_H 1)
|
||||
set(HAVE_WINSOCK2_H 1)
|
||||
|
||||
if(MINGW)
|
||||
set(HAVE_SNPRINTF 1)
|
||||
set(HAVE_UNISTD_H 1)
|
||||
set(HAVE_INTTYPES_H 1)
|
||||
set(HAVE_STRTOLL 1)
|
||||
elseif(MSVC)
|
||||
if(NOT MSVC_VERSION LESS 1800)
|
||||
set(HAVE_INTTYPES_H 1)
|
||||
set(HAVE_STRTOLL 1)
|
||||
else()
|
||||
set(HAVE_INTTYPES_H 0)
|
||||
set(HAVE_STRTOLL 0)
|
||||
endif()
|
||||
if(NOT MSVC_VERSION LESS 1900)
|
||||
set(HAVE_SNPRINTF 1)
|
||||
else()
|
||||
set(HAVE_SNPRINTF 0)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(HAVE_LIBSOCKET 0)
|
||||
set(HAVE_GETHOSTNAME 1)
|
||||
set(HAVE_LIBZ 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_NET_IF_H 0)
|
||||
set(HAVE_IOCTL_SIOCGIFADDR 0)
|
||||
set(HAVE_POLL_H 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_IOCTL_H 0)
|
||||
set(HAVE_SYS_PARAM_H 0)
|
||||
set(HAVE_SYS_POLL_H 0)
|
||||
set(HAVE_SYS_RESOURCE_H 0)
|
||||
set(HAVE_SYS_SELECT_H 0)
|
||||
set(HAVE_SYS_SOCKET_H 0)
|
||||
set(HAVE_SYS_SOCKIO_H 0)
|
||||
set(HAVE_SYS_STAT_H 1)
|
||||
set(HAVE_SYS_TIME_H 0)
|
||||
set(HAVE_SYS_TYPES_H 1)
|
||||
set(HAVE_SYS_UN_H 0)
|
||||
set(HAVE_SYS_UTIME_H 1)
|
||||
set(HAVE_TERMIOS_H 0)
|
||||
set(HAVE_TERMIO_H 0)
|
||||
@@ -66,10 +100,12 @@ if(NOT UNIX)
|
||||
set(HAVE_GETPWUID 0)
|
||||
set(HAVE_GETEUID 0)
|
||||
set(HAVE_UTIME 1)
|
||||
set(HAVE_RAND_EGD 0)
|
||||
set(HAVE_GMTIME_R 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_GETHOSTBYNAME_R_3 0)
|
||||
set(HAVE_GETHOSTBYNAME_R_3_REENTRANT 0)
|
||||
|
||||
@@ -33,3 +33,6 @@ endif()
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/@TARGETS_EXPORT_NAME@.cmake")
|
||||
check_required_components("@PROJECT_NAME@")
|
||||
|
||||
# Alias for either shared or static library
|
||||
add_library(@PROJECT_NAME@::libcurl ALIAS @PROJECT_NAME@::@LIB_SELECTED@)
|
||||
|
||||
+134
-95
@@ -194,10 +194,9 @@ endif()
|
||||
# https://cmake.org/cmake/help/latest/module/FetchContent.html#integrating-with-find-package
|
||||
#
|
||||
# The following variables are available:
|
||||
# HAVE_RAND_EGD: `RAND_egd` present in OpenSSL
|
||||
# HAVE_SSL_SET0_WBIO: `SSL_set0_wbio` present in OpenSSL
|
||||
# HAVE_AWSLC: OpenSSL is AWS-LC
|
||||
# HAVE_BORINGSSL: OpenSSL is BoringSSL
|
||||
# HAVE_PK11_CREATEMANAGEDGENERICOBJECTL: `PK11_CreateManagedGenericObject` present in NSS
|
||||
# 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
|
||||
@@ -248,6 +247,8 @@ 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_CURL "Build curl executable with static libcurl" OFF)
|
||||
option(ENABLE_ARES "Set to ON to enable c-ares support" OFF)
|
||||
if(WIN32)
|
||||
option(CURL_STATIC_CRT "Set to ON to build libcurl with static CRT on Windows (/MT)." OFF)
|
||||
@@ -297,6 +298,32 @@ if(NOT DEFINED CMAKE_DEBUG_POSTFIX)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(LIB_STATIC "libcurl_static")
|
||||
set(LIB_SHARED "libcurl_shared")
|
||||
|
||||
if(NOT BUILD_SHARED_LIBS AND NOT BUILD_STATIC_LIBS)
|
||||
set(BUILD_STATIC_LIBS ON)
|
||||
endif()
|
||||
if(NOT BUILD_STATIC_CURL AND NOT BUILD_SHARED_LIBS)
|
||||
set(BUILD_STATIC_CURL ON)
|
||||
elseif(BUILD_STATIC_CURL AND NOT BUILD_STATIC_LIBS)
|
||||
set(BUILD_STATIC_CURL OFF)
|
||||
endif()
|
||||
|
||||
# lib flavour selected for curl tool
|
||||
if(BUILD_STATIC_CURL)
|
||||
set(LIB_SELECTED_FOR_EXE ${LIB_STATIC})
|
||||
else()
|
||||
set(LIB_SELECTED_FOR_EXE ${LIB_SHARED})
|
||||
endif()
|
||||
|
||||
# lib flavour selected for example and test programs.
|
||||
if(BUILD_SHARED_LIBS)
|
||||
set(LIB_SELECTED ${LIB_SHARED})
|
||||
else()
|
||||
set(LIB_SELECTED ${LIB_STATIC})
|
||||
endif()
|
||||
|
||||
# initialize CURL_LIBS
|
||||
set(CURL_LIBS "")
|
||||
|
||||
@@ -317,14 +344,27 @@ option(CURL_DISABLE_ALTSVC "disables alt-svc support" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_ALTSVC)
|
||||
option(CURL_DISABLE_COOKIES "disables cookies support" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_COOKIES)
|
||||
option(CURL_DISABLE_CRYPTO_AUTH "disables cryptographic authentication" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_CRYPTO_AUTH)
|
||||
option(CURL_DISABLE_BASIC_AUTH "disables Basic authentication" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_BASIC_AUTH)
|
||||
option(CURL_DISABLE_BEARER_AUTH "disables Bearer authentication" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_BEARER_AUTH)
|
||||
option(CURL_DISABLE_DIGEST_AUTH "disables Digest authentication" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_DIGEST_AUTH)
|
||||
option(CURL_DISABLE_KERBEROS_AUTH "disables Kerberos authentication" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_KERBEROS_AUTH)
|
||||
option(CURL_DISABLE_NEGOTIATE_AUTH "disables negotiate authentication" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_NEGOTIATE_AUTH)
|
||||
option(CURL_DISABLE_AWS "disables AWS-SIG4" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_AWS)
|
||||
option(CURL_DISABLE_DICT "disables DICT" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_DICT)
|
||||
option(CURL_DISABLE_DOH "disables DNS-over-HTTPS" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_DOH)
|
||||
option(CURL_DISABLE_FILE "disables FILE" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_FILE)
|
||||
cmake_dependent_option(CURL_DISABLE_FORM_API "disables form api" OFF
|
||||
"NOT CURL_DISABLE_MIME" ON)
|
||||
mark_as_advanced(CURL_DISABLE_FORM_API)
|
||||
option(CURL_DISABLE_FTP "disables FTP" OFF)
|
||||
mark_as_advanced(CURL_DISABLE_FTP)
|
||||
option(CURL_DISABLE_GETOPTIONS "disables curl_easy_options API for existing options to curl_easy_setopt" OFF)
|
||||
@@ -496,8 +536,10 @@ check_library_exists_concat("socket" connect HAVE_LIBSOCKET)
|
||||
check_function_exists(gethostname HAVE_GETHOSTNAME)
|
||||
|
||||
if(WIN32)
|
||||
check_library_exists_concat("ws2_32" getch HAVE_LIBWS2_32)
|
||||
check_library_exists_concat("winmm" getch HAVE_LIBWINMM)
|
||||
list(APPEND CURL_LIBS "ws2_32")
|
||||
if(USE_LIBRTMP)
|
||||
list(APPEND CURL_LIBS "winmm")
|
||||
endif()
|
||||
|
||||
# Matching logic used for Curl_win32_random()
|
||||
if(MINGW)
|
||||
@@ -515,24 +557,23 @@ endif()
|
||||
|
||||
if(0) # This code not needed for building within CMake.
|
||||
# check SSL libraries
|
||||
# TODO support GnuTLS
|
||||
option(CURL_ENABLE_SSL "Enable SSL support" ON)
|
||||
|
||||
if(APPLE)
|
||||
cmake_dependent_option(CURL_USE_SECTRANSP "enable Apple OS native SSL/TLS" OFF CURL_ENABLE_SSL OFF)
|
||||
cmake_dependent_option(CURL_USE_SECTRANSP "Enable Apple OS native SSL/TLS" OFF CURL_ENABLE_SSL OFF)
|
||||
endif()
|
||||
if(WIN32)
|
||||
cmake_dependent_option(CURL_USE_SCHANNEL "enable Windows native SSL/TLS" OFF CURL_ENABLE_SSL OFF)
|
||||
cmake_dependent_option(CURL_USE_SCHANNEL "Enable Windows native SSL/TLS" OFF CURL_ENABLE_SSL OFF)
|
||||
cmake_dependent_option(CURL_WINDOWS_SSPI "Use windows libraries to allow NTLM authentication without OpenSSL" ON
|
||||
CURL_USE_SCHANNEL OFF)
|
||||
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_NSS "Enable NSS 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_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)
|
||||
|
||||
set(openssl_default ON)
|
||||
if(WIN32 OR CURL_USE_SECTRANSP OR CURL_USE_SCHANNEL OR CURL_USE_MBEDTLS OR CURL_USE_NSS OR CURL_USE_WOLFSSL)
|
||||
if(WIN32 OR CURL_USE_SECTRANSP OR CURL_USE_SCHANNEL OR CURL_USE_MBEDTLS OR CURL_USE_WOLFSSL)
|
||||
set(openssl_default OFF)
|
||||
endif()
|
||||
cmake_dependent_option(CURL_USE_OPENSSL "Use OpenSSL code. Experimental" ${openssl_default} CURL_ENABLE_SSL OFF)
|
||||
@@ -545,7 +586,6 @@ count_true(enabled_ssl_options_count
|
||||
CURL_USE_OPENSSL
|
||||
CURL_USE_MBEDTLS
|
||||
CURL_USE_BEARSSL
|
||||
CURL_USE_NSS
|
||||
CURL_USE_WOLFSSL
|
||||
)
|
||||
if(enabled_ssl_options_count GREATER "1")
|
||||
@@ -603,9 +643,6 @@ if(CURL_USE_OPENSSL)
|
||||
endif()
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
if(NOT DEFINED HAVE_RAND_EGD)
|
||||
check_symbol_exists(RAND_egd "${CURL_INCLUDES}" HAVE_RAND_EGD)
|
||||
endif()
|
||||
if(NOT DEFINED HAVE_BORINGSSL)
|
||||
check_symbol_exists(OPENSSL_IS_BORINGSSL "openssl/base.h" HAVE_BORINGSSL)
|
||||
endif()
|
||||
@@ -647,23 +684,13 @@ if(CURL_USE_WOLFSSL)
|
||||
include_directories(${WolfSSL_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
if(CURL_USE_NSS)
|
||||
find_package(NSS REQUIRED)
|
||||
include_directories(${NSS_INCLUDE_DIRS})
|
||||
list(APPEND CURL_LIBS ${NSS_LIBRARIES})
|
||||
set(SSL_ENABLED ON)
|
||||
set(USE_NSS ON)
|
||||
if(NOT DEFINED HAVE_PK11_CREATEMANAGEDGENERICOBJECT)
|
||||
cmake_push_check_state()
|
||||
set(CMAKE_REQUIRED_INCLUDES ${NSS_INCLUDE_DIRS})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${NSS_LIBRARIES})
|
||||
check_symbol_exists(PK11_CreateManagedGenericObject "pk11pub.h" HAVE_PK11_CREATEMANAGEDGENERICOBJECT)
|
||||
cmake_pop_check_state()
|
||||
endif()
|
||||
if(CURL_USE_GNUTLS)
|
||||
set(SSL_ENABLED ON)
|
||||
set(USE_GNUTLS ON)
|
||||
endif()
|
||||
|
||||
# Keep ZLIB detection after TLS detection,
|
||||
# and before calling CheckQuicSupportInOpenSSL.
|
||||
# and before calling openssl_check_symbol_exists().
|
||||
|
||||
set(HAVE_LIBZ OFF)
|
||||
set(USE_ZLIB OFF)
|
||||
@@ -694,6 +721,7 @@ if(CURL_BROTLI)
|
||||
find_package(Brotli REQUIRED)
|
||||
if(BROTLI_FOUND)
|
||||
set(HAVE_BROTLI ON)
|
||||
set(CURL_LIBS "${BROTLI_LIBRARIES};${CURL_LIBS}") # For 'ld' linker. Emulate `list(PREPEND ...)` to stay compatible with <v3.15 CMake.
|
||||
list(APPEND CURL_LIBS ${BROTLI_LIBRARIES})
|
||||
include_directories(${BROTLI_INCLUDE_DIRS})
|
||||
list(APPEND CMAKE_REQUIRED_INCLUDES ${BROTLI_INCLUDE_DIRS})
|
||||
@@ -718,50 +746,50 @@ if(CURL_ZSTD)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(USE_NGHTTP2 "Use Nghttp2 library" OFF)
|
||||
# Check symbol in OpenSSL-like TLS backends.
|
||||
macro(openssl_check_symbol_exists SYMBOL FILES VARIABLE)
|
||||
cmake_push_check_state()
|
||||
if(USE_OPENSSL)
|
||||
set(CMAKE_REQUIRED_INCLUDES "${OPENSSL_INCLUDE_DIR}")
|
||||
set(CMAKE_REQUIRED_LIBRARIES "${OPENSSL_LIBRARIES}")
|
||||
if(HAVE_LIBZ)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES "${ZLIB_LIBRARIES}")
|
||||
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()
|
||||
endif()
|
||||
elseif(USE_WOLFSSL)
|
||||
set(CMAKE_REQUIRED_INCLUDES "${WolfSSL_INCLUDE_DIRS}")
|
||||
set(CMAKE_REQUIRED_LIBRARIES "${WolfSSL_LIBRARIES}")
|
||||
if(HAVE_LIBZ)
|
||||
list(APPEND CMAKE_REQUIRED_INCLUDES "${ZLIB_INCLUDE_DIRS}") # Public wolfSSL headers require zlib headers
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES "${ZLIB_LIBRARIES}")
|
||||
endif()
|
||||
if(WIN32)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES "ws2_32" "crypt32")
|
||||
endif()
|
||||
list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_UINTPTR_T) # to pull in stdint.h (as of wolfSSL v5.5.4)
|
||||
endif()
|
||||
check_symbol_exists("${SYMBOL}" "${FILES}" "${VARIABLE}")
|
||||
cmake_pop_check_state()
|
||||
endmacro()
|
||||
|
||||
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()
|
||||
endif()
|
||||
|
||||
option(USE_NGHTTP2 "Use nghttp2 library" OFF)
|
||||
if(USE_NGHTTP2)
|
||||
find_package(NGHTTP2 REQUIRED)
|
||||
include_directories(${NGHTTP2_INCLUDE_DIRS})
|
||||
list(APPEND CURL_LIBS ${NGHTTP2_LIBRARIES})
|
||||
endif()
|
||||
|
||||
function(CheckQuicSupportInOpenSSL)
|
||||
# Be sure that the OpenSSL/wolfSSL library actually supports QUIC.
|
||||
if(NOT DEFINED HAVE_SSL_CTX_SET_QUIC_METHOD)
|
||||
cmake_push_check_state()
|
||||
if(USE_WOLFSSL)
|
||||
set(CMAKE_REQUIRED_INCLUDES "${WolfSSL_INCLUDE_DIRS}")
|
||||
set(CMAKE_REQUIRED_LIBRARIES "${WolfSSL_LIBRARIES}")
|
||||
if(HAVE_LIBZ)
|
||||
list(APPEND CMAKE_REQUIRED_INCLUDES "${ZLIB_INCLUDE_DIRS}") # Public wolfSSL headers require zlib headers
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES "${ZLIB_LIBRARIES}")
|
||||
endif()
|
||||
if(WIN32)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES "ws2_32" "crypt32")
|
||||
endif()
|
||||
list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_UINTPTR_T) # to pull in stdint.h (as of wolfSSL v5.5.4)
|
||||
check_symbol_exists(wolfSSL_set_quic_method "wolfssl/options.h;wolfssl/openssl/ssl.h" HAVE_SSL_CTX_SET_QUIC_METHOD)
|
||||
else()
|
||||
set(CMAKE_REQUIRED_INCLUDES "${OPENSSL_INCLUDE_DIR}")
|
||||
set(CMAKE_REQUIRED_LIBRARIES "${OPENSSL_LIBRARIES}")
|
||||
if(HAVE_LIBZ)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES "${ZLIB_LIBRARIES}")
|
||||
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()
|
||||
endif()
|
||||
check_symbol_exists(SSL_CTX_set_quic_method "openssl/ssl.h" HAVE_SSL_CTX_SET_QUIC_METHOD)
|
||||
endif()
|
||||
cmake_pop_check_state()
|
||||
endif()
|
||||
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()
|
||||
endfunction()
|
||||
|
||||
option(USE_NGTCP2 "Use ngtcp2 and nghttp3 libraries for HTTP/3 support" OFF)
|
||||
if(USE_NGTCP2)
|
||||
if(USE_OPENSSL OR USE_WOLFSSL)
|
||||
@@ -772,7 +800,19 @@ if(USE_NGTCP2)
|
||||
else()
|
||||
find_package(NGTCP2 REQUIRED quictls)
|
||||
endif()
|
||||
CheckQuicSupportInOpenSSL()
|
||||
|
||||
# Be sure that the OpenSSL/wolfSSL library actually supports QUIC.
|
||||
if(NOT DEFINED HAVE_SSL_CTX_SET_QUIC_METHOD)
|
||||
if(USE_OPENSSL)
|
||||
openssl_check_symbol_exists(SSL_CTX_set_quic_method "openssl/ssl.h" HAVE_SSL_CTX_SET_QUIC_METHOD)
|
||||
elseif(USE_WOLFSSL)
|
||||
openssl_check_symbol_exists(wolfSSL_set_quic_method "wolfssl/options.h;wolfssl/openssl/ssl.h" HAVE_SSL_CTX_SET_QUIC_METHOD)
|
||||
endif()
|
||||
endif()
|
||||
if(NOT HAVE_SSL_CTX_SET_QUIC_METHOD)
|
||||
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)
|
||||
@@ -822,10 +862,8 @@ if(NOT CURL_DISABLE_LDAP)
|
||||
if(WIN32)
|
||||
option(USE_WIN32_LDAP "Use Windows LDAP implementation" ON)
|
||||
if(USE_WIN32_LDAP)
|
||||
check_library_exists_concat("wldap32" cldap_open HAVE_WLDAP32)
|
||||
if(NOT HAVE_WLDAP32)
|
||||
set(USE_WIN32_LDAP OFF)
|
||||
elseif(NOT CURL_DISABLE_LDAPS)
|
||||
list(APPEND CURL_LIBS "wldap32")
|
||||
if(NOT CURL_DISABLE_LDAPS)
|
||||
set(HAVE_LDAP_SSL ON)
|
||||
endif()
|
||||
endif()
|
||||
@@ -1089,7 +1127,7 @@ elseif("${CURL_CA_PATH}" STREQUAL "none")
|
||||
unset(CURL_CA_PATH CACHE)
|
||||
elseif("${CURL_CA_PATH}" STREQUAL "auto")
|
||||
unset(CURL_CA_PATH CACHE)
|
||||
if(NOT CMAKE_CROSSCOMPILING AND NOT USE_NSS)
|
||||
if(NOT CMAKE_CROSSCOMPILING)
|
||||
set(CURL_CA_PATH_AUTODETECT TRUE)
|
||||
endif()
|
||||
else()
|
||||
@@ -1143,7 +1181,6 @@ if(NOT UNIX)
|
||||
check_include_file_concat("windows.h" HAVE_WINDOWS_H)
|
||||
check_include_file_concat("ws2tcpip.h" HAVE_WS2TCPIP_H)
|
||||
check_include_file_concat("winsock2.h" HAVE_WINSOCK2_H)
|
||||
check_include_file_concat("wincrypt.h" HAVE_WINCRYPT_H)
|
||||
else()
|
||||
set(HAVE_WINDOWS_H 0)
|
||||
set(HAVE_WS2TCPIP_H 0)
|
||||
@@ -1183,7 +1220,6 @@ 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("ssl.h" HAVE_SSL_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)
|
||||
@@ -1198,7 +1234,6 @@ 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_include_file_concat("sys/utsname.h" HAVE_SYS_UTSNAME_H)
|
||||
|
||||
check_type_size(size_t SIZEOF_SIZE_T)
|
||||
check_type_size(ssize_t SIZEOF_SSIZE_T)
|
||||
@@ -1210,7 +1245,7 @@ if(NOT CMAKE_CROSSCOMPILING)
|
||||
endif()
|
||||
|
||||
# Check for some functions that are used
|
||||
if(HAVE_LIBWS2_32)
|
||||
if(WIN32)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ws2_32)
|
||||
elseif(HAVE_LIBSOCKET)
|
||||
set(CMAKE_REQUIRED_LIBRARIES socket)
|
||||
@@ -1469,11 +1504,8 @@ if(WIN32)
|
||||
# Use the manifest embedded in the Windows Resource
|
||||
set(CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS} -DCURL_EMBED_MANIFEST")
|
||||
|
||||
# Check if crypto functions in wincrypt.h are actually available
|
||||
if(HAVE_WINCRYPT_H)
|
||||
check_symbol_exists(CryptAcquireContext "windows.h;wincrypt.h" USE_WINCRYPT)
|
||||
endif()
|
||||
if(USE_WINCRYPT)
|
||||
# We use crypto functions that are not available for UWP apps
|
||||
if(NOT WINDOWS_STORE)
|
||||
set(USE_WIN32_CRYPTO ON)
|
||||
endif()
|
||||
|
||||
@@ -1601,8 +1633,8 @@ endmacro()
|
||||
|
||||
# NTLM support requires crypto function adaptions from various SSL libs
|
||||
# TODO alternative SSL libs tests for SSP1, GNUTLS, NSS
|
||||
if(NOT (CURL_DISABLE_CRYPTO_AUTH OR CURL_DISABLE_NTLM) AND
|
||||
(USE_OPENSSL OR USE_MBEDTLS OR USE_DARWINSSL OR USE_WIN32_CRYPTO))
|
||||
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)
|
||||
endif()
|
||||
|
||||
@@ -1624,16 +1656,16 @@ _add_if("GSS-API" HAVE_GSSAPI)
|
||||
_add_if("alt-svc" NOT CURL_DISABLE_ALTSVC)
|
||||
_add_if("HSTS" NOT CURL_DISABLE_HSTS)
|
||||
# TODO SSP1 missing for SPNEGO
|
||||
_add_if("SPNEGO" NOT CURL_DISABLE_CRYPTO_AUTH AND
|
||||
_add_if("SPNEGO" NOT CURL_DISABLE_NEGOTIATE_AUTH AND
|
||||
(HAVE_GSSAPI OR USE_WINDOWS_SSPI))
|
||||
_add_if("Kerberos" NOT CURL_DISABLE_CRYPTO_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
|
||||
_add_if("NTLM" NOT (CURL_DISABLE_CRYPTO_AUTH OR CURL_DISABLE_NTLM) AND
|
||||
_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_CRYPTO_AUTH OR CURL_DISABLE_NTLM) AND
|
||||
_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
|
||||
@@ -1643,7 +1675,7 @@ _add_if("HTTP2" USE_NGHTTP2)
|
||||
_add_if("HTTP3" USE_NGTCP2 OR USE_QUICHE)
|
||||
_add_if("MultiSSL" CURL_WITH_MULTI_SSL)
|
||||
# TODO wolfSSL only support this from v5.0.0 onwards
|
||||
_add_if("HTTPS-proxy" SSL_ENABLED AND (USE_OPENSSL OR USE_GNUTLS OR USE_NSS
|
||||
_add_if("HTTPS-proxy" SSL_ENABLED AND (USE_OPENSSL OR USE_GNUTLS
|
||||
OR USE_SCHANNEL OR USE_RUSTLS OR USE_BEARSSL OR
|
||||
USE_MBEDTLS OR USE_SECTRANSP))
|
||||
_add_if("unicode" ENABLE_UNICODE)
|
||||
@@ -1701,20 +1733,22 @@ _add_if("OpenSSL" SSL_ENABLED AND USE_OPENSSL)
|
||||
_add_if("Secure Transport" SSL_ENABLED AND USE_SECTRANSP)
|
||||
_add_if("mbedTLS" SSL_ENABLED AND USE_MBEDTLS)
|
||||
_add_if("BearSSL" SSL_ENABLED AND USE_BEARSSL)
|
||||
_add_if("NSS" SSL_ENABLED AND USE_NSS)
|
||||
_add_if("wolfSSL" SSL_ENABLED AND USE_WOLFSSL)
|
||||
_add_if("GnuTLS" SSL_ENABLED AND USE_GNUTLS)
|
||||
|
||||
if(_items)
|
||||
list(SORT _items)
|
||||
endif()
|
||||
string(REPLACE ";" " " SSL_BACKENDS "${_items}")
|
||||
message(STATUS "Enabled SSL backends: ${SSL_BACKENDS}")
|
||||
if(CURL_DEFAULT_SSL_BACKEND)
|
||||
message(STATUS "Default SSL backend: ${CURL_DEFAULT_SSL_BACKEND}")
|
||||
endif()
|
||||
|
||||
# curl-config needs the following options to be set.
|
||||
set(CC "${CMAKE_C_COMPILER}")
|
||||
# TODO probably put a -D... options here?
|
||||
set(CONFIGURE_OPTIONS "")
|
||||
# TODO when to set "-DCURL_STATICLIB" for CPPFLAG_CURL_STATICLIB?
|
||||
set(CPPFLAG_CURL_STATICLIB "")
|
||||
set(CURLVERSION "${CURL_VERSION}")
|
||||
set(exec_prefix "\${prefix}")
|
||||
set(includedir "\${prefix}/include")
|
||||
@@ -1744,12 +1778,17 @@ foreach(_lib ${CMAKE_C_IMPLICIT_LINK_LIBRARIES} ${CURL_LIBS})
|
||||
endforeach()
|
||||
if(BUILD_SHARED_LIBS)
|
||||
set(ENABLE_SHARED "yes")
|
||||
set(ENABLE_STATIC "no")
|
||||
set(LIBCURL_NO_SHARED "")
|
||||
set(CPPFLAG_CURL_STATICLIB "")
|
||||
else()
|
||||
set(ENABLE_SHARED "no")
|
||||
set(ENABLE_STATIC "yes")
|
||||
set(LIBCURL_NO_SHARED "${LIBCURL_LIBS}")
|
||||
set(CPPFLAG_CURL_STATICLIB "-DCURL_STATICLIB")
|
||||
endif()
|
||||
if(BUILD_STATIC_LIBS)
|
||||
set(ENABLE_STATIC "yes")
|
||||
else()
|
||||
set(ENABLE_STATIC "no")
|
||||
endif()
|
||||
# "a" (Linux) or "lib" (Windows)
|
||||
string(REPLACE "." "" libext "${CMAKE_STATIC_LIBRARY_SUFFIX}")
|
||||
|
||||
@@ -161,7 +161,7 @@ typedef enum {
|
||||
CURLSSLBACKEND_GNUTLS = 2,
|
||||
CURLSSLBACKEND_NSS = 3,
|
||||
CURLSSLBACKEND_OBSOLETE4 = 4, /* Was QSOSSL. */
|
||||
CURLSSLBACKEND_GSKIT = 5,
|
||||
CURLSSLBACKEND_GSKIT CURL_DEPRECATED(8.3.0, "") = 5,
|
||||
CURLSSLBACKEND_POLARSSL CURL_DEPRECATED(7.69.0, "") = 6,
|
||||
CURLSSLBACKEND_WOLFSSL = 7,
|
||||
CURLSSLBACKEND_SCHANNEL = 8,
|
||||
@@ -2731,6 +2731,20 @@ CURL_EXTERN CURLcode curl_global_init_mem(long flags,
|
||||
*/
|
||||
CURL_EXTERN void curl_global_cleanup(void);
|
||||
|
||||
/*
|
||||
* NAME curl_global_trace()
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* curl_global_trace() can be invoked at application start to
|
||||
* configure which components in curl should participate in tracing.
|
||||
|
||||
* This function is thread-safe if CURL_VERSION_THREADSAFE is set in the
|
||||
* curl_version_info_data.features flag (fetch by curl_version_info()).
|
||||
|
||||
*/
|
||||
CURL_EXTERN CURLcode curl_global_trace(const char *config);
|
||||
|
||||
/* linked-list structure for the CURLOPT_QUOTE option (and other) */
|
||||
struct curl_slist {
|
||||
char *data;
|
||||
@@ -2810,13 +2824,14 @@ CURL_EXTERN void curl_slist_free_all(struct curl_slist *list);
|
||||
*/
|
||||
CURL_EXTERN time_t curl_getdate(const char *p, const time_t *unused);
|
||||
|
||||
/* info about the certificate chain, only for OpenSSL, GnuTLS, Schannel, NSS
|
||||
and GSKit builds. Asked for with CURLOPT_CERTINFO / CURLINFO_CERTINFO */
|
||||
/* info about the certificate chain, for SSL backends that support it. Asked
|
||||
for with CURLOPT_CERTINFO / CURLINFO_CERTINFO */
|
||||
struct curl_certinfo {
|
||||
int num_of_certs; /* number of certificates with information */
|
||||
struct curl_slist **certinfo; /* for each index in this array, there's a
|
||||
linked list with textual information in the
|
||||
format "name: value" */
|
||||
linked list with textual information for a
|
||||
certificate in the format "name:content".
|
||||
eg "Subject:foo", "Issuer:bar", etc. */
|
||||
};
|
||||
|
||||
/* Information about the SSL library used and the respective internal SSL
|
||||
|
||||
@@ -32,13 +32,13 @@
|
||||
|
||||
/* This is the version number of the libcurl package from which this header
|
||||
file origins: */
|
||||
#define LIBCURL_VERSION "8.2.1"
|
||||
#define LIBCURL_VERSION "8.3.0"
|
||||
|
||||
/* The numeric version number is also available "in parts" by using these
|
||||
defines: */
|
||||
#define LIBCURL_VERSION_MAJOR 8
|
||||
#define LIBCURL_VERSION_MINOR 2
|
||||
#define LIBCURL_VERSION_PATCH 1
|
||||
#define LIBCURL_VERSION_MINOR 3
|
||||
#define LIBCURL_VERSION_PATCH 0
|
||||
|
||||
/* This is the numeric version of the libcurl version number, meant for easier
|
||||
parsing and comparisons by programs. The LIBCURL_VERSION_NUM define will
|
||||
@@ -59,7 +59,7 @@
|
||||
CURL_VERSION_BITS() macro since curl's own configure script greps for it
|
||||
and needs it to contain the full number.
|
||||
*/
|
||||
#define LIBCURL_VERSION_NUM 0x080201
|
||||
#define LIBCURL_VERSION_NUM 0x080300
|
||||
|
||||
/*
|
||||
* This is the date and time when the full source package was created. The
|
||||
|
||||
@@ -32,18 +32,36 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
CURL_EXTERN int curl_mprintf(const char *format, ...);
|
||||
CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...);
|
||||
CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...);
|
||||
#if (defined(__GNUC__) || defined(__clang__)) && \
|
||||
defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
|
||||
!defined(__MINGW32__) && !defined(CURL_NO_FMT_CHECKS)
|
||||
#define CURL_TEMP_PRINTF(a,b) __attribute__ ((format(printf, a, b)))
|
||||
#else
|
||||
#define CURL_TEMP_PRINTF(a,b)
|
||||
#endif
|
||||
|
||||
CURL_EXTERN int curl_mprintf(const char *format, ...) CURL_TEMP_PRINTF(1, 2);
|
||||
CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...)
|
||||
CURL_TEMP_PRINTF(2, 3);
|
||||
CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...)
|
||||
CURL_TEMP_PRINTF(2, 3);
|
||||
CURL_EXTERN int curl_msnprintf(char *buffer, size_t maxlength,
|
||||
const char *format, ...);
|
||||
CURL_EXTERN int curl_mvprintf(const char *format, va_list args);
|
||||
CURL_EXTERN int curl_mvfprintf(FILE *fd, const char *format, va_list args);
|
||||
CURL_EXTERN int curl_mvsprintf(char *buffer, const char *format, va_list args);
|
||||
const char *format, ...) CURL_TEMP_PRINTF(3, 4);
|
||||
CURL_EXTERN int curl_mvprintf(const char *format, va_list args)
|
||||
CURL_TEMP_PRINTF(1, 0);
|
||||
CURL_EXTERN int curl_mvfprintf(FILE *fd, const char *format, va_list args)
|
||||
CURL_TEMP_PRINTF(2, 0);
|
||||
CURL_EXTERN int curl_mvsprintf(char *buffer, const char *format, va_list args)
|
||||
CURL_TEMP_PRINTF(2, 0);
|
||||
CURL_EXTERN int curl_mvsnprintf(char *buffer, size_t maxlength,
|
||||
const char *format, va_list args);
|
||||
CURL_EXTERN char *curl_maprintf(const char *format, ...);
|
||||
CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args);
|
||||
const char *format, va_list args)
|
||||
CURL_TEMP_PRINTF(3, 0);
|
||||
CURL_EXTERN char *curl_maprintf(const char *format, ...)
|
||||
CURL_TEMP_PRINTF(1, 2);
|
||||
CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args)
|
||||
CURL_TEMP_PRINTF(1, 0);
|
||||
|
||||
#undef CURL_TEMP_PRINTF
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end of extern "C" */
|
||||
|
||||
@@ -118,7 +118,7 @@ typedef struct CURLMsg CURLMsg;
|
||||
struct curl_waitfd {
|
||||
curl_socket_t fd;
|
||||
short events;
|
||||
short revents; /* not supported yet */
|
||||
short revents;
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -347,6 +347,24 @@
|
||||
# define CURL_PULL_SYS_TYPES_H 1
|
||||
# define CURL_PULL_SYS_SOCKET_H 1
|
||||
|
||||
#elif defined(__hpux) /* HP aCC compiler */
|
||||
# if !defined(_LP64)
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T LL
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# else
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# endif
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
|
||||
# define CURL_PULL_SYS_TYPES_H 1
|
||||
# define CURL_PULL_SYS_SOCKET_H 1
|
||||
|
||||
/* ===================================== */
|
||||
/* KEEP MSVC THE PENULTIMATE ENTRY */
|
||||
/* ===================================== */
|
||||
|
||||
@@ -96,7 +96,8 @@ typedef enum {
|
||||
#define CURLU_NO_AUTHORITY (1<<10) /* Allow empty authority when the
|
||||
scheme is unknown. */
|
||||
#define CURLU_ALLOW_SPACE (1<<11) /* Allow spaces in the URL */
|
||||
#define CURLU_PUNYCODE (1<<12) /* get the host name in pynycode */
|
||||
#define CURLU_PUNYCODE (1<<12) /* get the host name in punycode */
|
||||
#define CURLU_PUNY2IDN (1<<13) /* punycode => IDN conversion */
|
||||
|
||||
typedef struct Curl_URL CURLU;
|
||||
|
||||
|
||||
@@ -21,18 +21,10 @@
|
||||
# SPDX-License-Identifier: curl
|
||||
#
|
||||
###########################################################################
|
||||
set(LIB_NAME cmcurl)
|
||||
set(LIBCURL_OUTPUT_NAME cmcurl)
|
||||
set(LIB_NAME libcurl)
|
||||
set(LIBCURL_OUTPUT_NAME libcurl CACHE STRING "Basename of the curl library")
|
||||
add_definitions(-DBUILDING_LIBCURL)
|
||||
|
||||
if(BUILD_SHARED_LIBS)
|
||||
set(CURL_STATICLIB NO)
|
||||
else()
|
||||
set(CURL_STATICLIB YES)
|
||||
endif()
|
||||
|
||||
# Use:
|
||||
# * CURL_STATICLIB
|
||||
configure_file(curl_config.h.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/curl_config.h)
|
||||
|
||||
@@ -43,10 +35,6 @@ list(APPEND HHEADERS
|
||||
${CMAKE_CURRENT_BINARY_DIR}/curl_config.h
|
||||
)
|
||||
|
||||
if(WIN32 AND NOT CURL_STATICLIB)
|
||||
list(APPEND CSOURCES libcurl.rc)
|
||||
endif()
|
||||
|
||||
# The rest of the build
|
||||
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR}/../include)
|
||||
@@ -83,13 +71,6 @@ if(CURL_USE_OPENSSL AND OPENSSL_FOUND AND WIN32)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_library(
|
||||
${LIB_NAME}
|
||||
${HHEADERS} ${CSOURCES}
|
||||
${CMAKE_CURL_SSL_DLLS}
|
||||
)
|
||||
|
||||
if(0) # This code not needed for building within CMake.
|
||||
add_library(
|
||||
curlu # special libcurlu library just for unittests
|
||||
STATIC
|
||||
@@ -97,43 +78,17 @@ add_library(
|
||||
${HHEADERS} ${CSOURCES}
|
||||
)
|
||||
target_compile_definitions(curlu PUBLIC UNITTESTS CURL_STATICLIB)
|
||||
endif()
|
||||
|
||||
add_library(
|
||||
${PROJECT_NAME}::${LIB_NAME}
|
||||
ALIAS ${LIB_NAME}
|
||||
)
|
||||
|
||||
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)
|
||||
endif()
|
||||
|
||||
if(NOT BUILD_SHARED_LIBS)
|
||||
set_target_properties(${LIB_NAME} PROPERTIES INTERFACE_COMPILE_DEFINITIONS CURL_STATICLIB)
|
||||
endif()
|
||||
|
||||
target_link_libraries(${LIB_NAME} PRIVATE ${CURL_LIBS})
|
||||
if(0) # This code not needed for building within CMake.
|
||||
target_link_libraries(curlu PRIVATE ${CURL_LIBS})
|
||||
endif()
|
||||
|
||||
if(0) # This code not needed for building within CMake.
|
||||
transform_makefile_inc("Makefile.soname" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake")
|
||||
include(${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake)
|
||||
endif()
|
||||
|
||||
set_target_properties(${LIB_NAME} PROPERTIES
|
||||
COMPILE_DEFINITIONS BUILDING_LIBCURL
|
||||
OUTPUT_NAME ${LIBCURL_OUTPUT_NAME}
|
||||
)
|
||||
|
||||
if(WIN32 AND CMake_BUILD_PCH)
|
||||
target_precompile_headers(${LIB_NAME} PRIVATE "curl_setup.h" "curl_sspi.h" "${CURL_SOURCE_DIR}/include/curl/curl.h")
|
||||
endif()
|
||||
|
||||
if(0) # This code not needed for building within CMake.
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "AIX" OR
|
||||
CMAKE_SYSTEM_NAME STREQUAL "Linux" OR
|
||||
CMAKE_SYSTEM_NAME STREQUAL "Darwin" OR
|
||||
@@ -150,39 +105,11 @@ if(CMAKE_SYSTEM_NAME STREQUAL "AIX" OR
|
||||
|
||||
math(EXPR CMAKESONAME "${VERSIONCHANGE} - ${VERSIONDEL}")
|
||||
set(CMAKEVERSION "${CMAKESONAME}.${VERSIONDEL}.${VERSIONADD}")
|
||||
|
||||
set_target_properties(${LIB_NAME} PROPERTIES
|
||||
VERSION ${CMAKEVERSION}
|
||||
SOVERSION ${CMAKESONAME}
|
||||
)
|
||||
|
||||
else()
|
||||
unset(CMAKESONAME)
|
||||
endif()
|
||||
|
||||
|
||||
if(HIDES_CURL_PRIVATE_SYMBOLS)
|
||||
set_property(TARGET ${LIB_NAME} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS")
|
||||
set_property(TARGET ${LIB_NAME} APPEND PROPERTY COMPILE_FLAGS ${CURL_CFLAG_SYMBOLS_HIDE})
|
||||
endif()
|
||||
|
||||
# Remove the "lib" prefix since the library is already named "libcurl".
|
||||
set_target_properties(${LIB_NAME} PROPERTIES PREFIX "")
|
||||
set_target_properties(${LIB_NAME} PROPERTIES IMPORT_PREFIX "")
|
||||
|
||||
if(CURL_HAS_LTO)
|
||||
set_target_properties(${LIB_NAME} PROPERTIES
|
||||
INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE
|
||||
INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
if(BUILD_SHARED_LIBS)
|
||||
if(MSVC)
|
||||
# Add "_imp" as a suffix before the extension to avoid conflicting with
|
||||
# the statically linked "libcurl.lib"
|
||||
set_target_properties(${LIB_NAME} PROPERTIES IMPORT_SUFFIX "_imp.lib")
|
||||
endif()
|
||||
endif()
|
||||
elseif(NOT CMAKE_CROSSCOMPILING)
|
||||
if(NOT WIN32 AND NOT CMAKE_CROSSCOMPILING)
|
||||
# on not-Windows and not-crosscompiling, check for writable argv[]
|
||||
include(CheckCSourceRuns)
|
||||
check_c_source_runs("
|
||||
@@ -195,22 +122,147 @@ int main(int argc, char **argv)
|
||||
HAVE_WRITABLE_ARGV)
|
||||
endif()
|
||||
|
||||
target_include_directories(${LIB_NAME} INTERFACE
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
$<BUILD_INTERFACE:${CURL_SOURCE_DIR}/include>)
|
||||
## Library definition
|
||||
|
||||
# Add "_imp" as a suffix before the extension to avoid conflicting with
|
||||
# the statically linked "libcurl.lib" (typically with MSVC)
|
||||
if(WIN32 AND
|
||||
NOT IMPORT_LIB_SUFFIX AND
|
||||
CMAKE_STATIC_LIBRARY_SUFFIX STREQUAL CMAKE_IMPORT_LIBRARY_SUFFIX)
|
||||
set(IMPORT_LIB_SUFFIX "_imp")
|
||||
endif()
|
||||
|
||||
# Whether to do a single compilation pass for libcurl sources and reuse these
|
||||
# objects to generate both static and shared target.
|
||||
if(NOT DEFINED SHARE_LIB_OBJECT)
|
||||
# Enable it by default on platforms where PIC is the default for both shared
|
||||
# and static and there is a way to tell the linker which libcurl symbols it
|
||||
# should export (vs. marking these symbols exportable at compile-time).
|
||||
if(WIN32)
|
||||
set(SHARE_LIB_OBJECT ON)
|
||||
else()
|
||||
# On other platforms, make it an option disabled by default
|
||||
set(SHARE_LIB_OBJECT OFF)
|
||||
endif()
|
||||
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}")
|
||||
endif()
|
||||
if(CURL_HAS_LTO)
|
||||
set_target_properties(${LIB_OBJECT} PROPERTIES
|
||||
INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE
|
||||
INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE)
|
||||
endif()
|
||||
|
||||
target_include_directories(${LIB_OBJECT} INTERFACE
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
$<BUILD_INTERFACE:${CURL_SOURCE_DIR}/include>)
|
||||
|
||||
set(LIB_SOURCE $<TARGET_OBJECTS:${LIB_OBJECT}>)
|
||||
else()
|
||||
set(LIB_SOURCE ${HHEADERS} ${CSOURCES})
|
||||
endif()
|
||||
|
||||
# we want it to be called libcurl on all platforms
|
||||
if(BUILD_STATIC_LIBS)
|
||||
list(APPEND libcurl_export ${LIB_STATIC})
|
||||
add_library(${LIB_STATIC} STATIC ${LIB_SOURCE})
|
||||
add_library(${PROJECT_NAME}::${LIB_STATIC} ALIAS ${LIB_STATIC})
|
||||
target_link_libraries(${LIB_STATIC} PRIVATE ${CURL_LIBS})
|
||||
# Remove the "lib" prefix since the library is already named "libcurl".
|
||||
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}")
|
||||
endif()
|
||||
if(CURL_HAS_LTO)
|
||||
set_target_properties(${LIB_STATIC} PROPERTIES
|
||||
INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE
|
||||
INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE)
|
||||
endif()
|
||||
if(CMAKEVERSION AND CMAKESONAME)
|
||||
set_target_properties(${LIB_STATIC} PROPERTIES
|
||||
VERSION ${CMAKEVERSION} SOVERSION ${CMAKESONAME})
|
||||
endif()
|
||||
|
||||
target_include_directories(${LIB_STATIC} INTERFACE
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
$<BUILD_INTERFACE:${CURL_SOURCE_DIR}/include>)
|
||||
endif()
|
||||
|
||||
if(BUILD_SHARED_LIBS)
|
||||
list(APPEND libcurl_export ${LIB_SHARED})
|
||||
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)
|
||||
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}")
|
||||
endif()
|
||||
if(CURL_HAS_LTO)
|
||||
set_target_properties(${LIB_SHARED} PROPERTIES
|
||||
INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE
|
||||
INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE)
|
||||
endif()
|
||||
if(CMAKEVERSION AND CMAKESONAME)
|
||||
set_target_properties(${LIB_SHARED} PROPERTIES
|
||||
VERSION ${CMAKEVERSION} SOVERSION ${CMAKESONAME})
|
||||
endif()
|
||||
|
||||
target_include_directories(${LIB_SHARED} INTERFACE
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
$<BUILD_INTERFACE:${CURL_SOURCE_DIR}/include>)
|
||||
endif()
|
||||
|
||||
add_library(${LIB_NAME} ALIAS ${LIB_SELECTED})
|
||||
add_library(${PROJECT_NAME}::${LIB_NAME} ALIAS ${LIB_SELECTED})
|
||||
|
||||
if(CURL_ENABLE_EXPORT_TARGET)
|
||||
install(TARGETS ${LIB_NAME}
|
||||
EXPORT ${TARGETS_EXPORT_NAME}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
if(BUILD_STATIC_LIBS)
|
||||
install(TARGETS ${LIB_STATIC}
|
||||
EXPORT ${TARGETS_EXPORT_NAME}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
endif()
|
||||
if(BUILD_SHARED_LIBS)
|
||||
install(TARGETS ${LIB_SHARED}
|
||||
EXPORT ${TARGETS_EXPORT_NAME}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
endif()
|
||||
|
||||
export(TARGETS ${LIB_NAME}
|
||||
export(TARGETS ${libcurl_export}
|
||||
FILE ${PROJECT_BINARY_DIR}/libcurl-target.cmake
|
||||
NAMESPACE ${PROJECT_NAME}::
|
||||
)
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
@@ -44,13 +44,11 @@ LIB_VAUTH_HFILES = \
|
||||
|
||||
LIB_VTLS_CFILES = \
|
||||
vtls/bearssl.c \
|
||||
vtls/gskit.c \
|
||||
vtls/gtls.c \
|
||||
vtls/hostcheck.c \
|
||||
vtls/keylog.c \
|
||||
vtls/mbedtls.c \
|
||||
vtls/mbedtls_threadlock.c \
|
||||
vtls/nss.c \
|
||||
vtls/openssl.c \
|
||||
vtls/rustls.c \
|
||||
vtls/schannel.c \
|
||||
@@ -62,13 +60,11 @@ LIB_VTLS_CFILES = \
|
||||
|
||||
LIB_VTLS_HFILES = \
|
||||
vtls/bearssl.h \
|
||||
vtls/gskit.h \
|
||||
vtls/gtls.h \
|
||||
vtls/hostcheck.h \
|
||||
vtls/keylog.h \
|
||||
vtls/mbedtls.h \
|
||||
vtls/mbedtls_threadlock.h \
|
||||
vtls/nssg.h \
|
||||
vtls/openssl.h \
|
||||
vtls/rustls.h \
|
||||
vtls/schannel.h \
|
||||
@@ -126,7 +122,6 @@ LIB_CFILES = \
|
||||
curl_get_line.c \
|
||||
curl_gethostname.c \
|
||||
curl_gssapi.c \
|
||||
curl_log.c \
|
||||
curl_memrchr.c \
|
||||
curl_multibyte.c \
|
||||
curl_ntlm_core.c \
|
||||
@@ -137,6 +132,7 @@ LIB_CFILES = \
|
||||
curl_sasl.c \
|
||||
curl_sspi.c \
|
||||
curl_threads.c \
|
||||
curl_trc.c \
|
||||
dict.c \
|
||||
doh.c \
|
||||
dynbuf.c \
|
||||
@@ -262,7 +258,6 @@ LIB_HFILES = \
|
||||
curl_hmac.h \
|
||||
curl_krb5.h \
|
||||
curl_ldap.h \
|
||||
curl_log.h \
|
||||
curl_md4.h \
|
||||
curl_md5.h \
|
||||
curl_memory.h \
|
||||
@@ -280,6 +275,7 @@ LIB_HFILES = \
|
||||
curl_sha256.h \
|
||||
curl_sspi.h \
|
||||
curl_threads.h \
|
||||
curl_trc.h \
|
||||
curlx.h \
|
||||
dict.h \
|
||||
doh.h \
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
#include "warnless.h"
|
||||
#include "fopen.h"
|
||||
#include "rename.h"
|
||||
#include "strdup.h"
|
||||
#include "inet_pton.h"
|
||||
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
@@ -97,19 +99,39 @@ static struct altsvc *altsvc_createid(const char *srchost,
|
||||
{
|
||||
struct altsvc *as = calloc(sizeof(struct altsvc), 1);
|
||||
size_t hlen;
|
||||
size_t dlen;
|
||||
if(!as)
|
||||
return NULL;
|
||||
hlen = strlen(srchost);
|
||||
dlen = strlen(dsthost);
|
||||
DEBUGASSERT(hlen);
|
||||
as->src.host = strdup(srchost);
|
||||
DEBUGASSERT(dlen);
|
||||
if(!hlen || !dlen)
|
||||
/* bad input */
|
||||
return NULL;
|
||||
if((hlen > 2) && srchost[0] == '[') {
|
||||
/* IPv6 address, strip off brackets */
|
||||
srchost++;
|
||||
hlen -= 2;
|
||||
}
|
||||
else if(srchost[hlen - 1] == '.')
|
||||
/* strip off trailing dot */
|
||||
hlen--;
|
||||
if((dlen > 2) && dsthost[0] == '[') {
|
||||
/* IPv6 address, strip off brackets */
|
||||
dsthost++;
|
||||
dlen -= 2;
|
||||
}
|
||||
|
||||
as->src.host = Curl_memdup(srchost, hlen + 1);
|
||||
if(!as->src.host)
|
||||
goto error;
|
||||
if(hlen && (srchost[hlen - 1] == '.'))
|
||||
/* strip off trailing any dot */
|
||||
as->src.host[--hlen] = 0;
|
||||
as->dst.host = strdup(dsthost);
|
||||
as->src.host[hlen] = 0;
|
||||
|
||||
as->dst.host = Curl_memdup(dsthost, dlen + 1);
|
||||
if(!as->dst.host)
|
||||
goto error;
|
||||
as->dst.host[dlen] = 0;
|
||||
|
||||
as->src.alpnid = srcalpnid;
|
||||
as->dst.alpnid = dstalpnid;
|
||||
@@ -231,18 +253,40 @@ fail:
|
||||
static CURLcode altsvc_out(struct altsvc *as, FILE *fp)
|
||||
{
|
||||
struct tm stamp;
|
||||
const char *dst6_pre = "";
|
||||
const char *dst6_post = "";
|
||||
const char *src6_pre = "";
|
||||
const char *src6_post = "";
|
||||
CURLcode result = Curl_gmtime(as->expires, &stamp);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
#ifdef ENABLE_IPV6
|
||||
else {
|
||||
char ipv6_unused[16];
|
||||
if(1 == Curl_inet_pton(AF_INET6, as->dst.host, ipv6_unused)) {
|
||||
dst6_pre = "[";
|
||||
dst6_post = "]";
|
||||
}
|
||||
if(1 == Curl_inet_pton(AF_INET6, as->src.host, ipv6_unused)) {
|
||||
src6_pre = "[";
|
||||
src6_post = "]";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
fprintf(fp,
|
||||
"%s %s %u "
|
||||
"%s %s %u "
|
||||
"%s %s%s%s %u "
|
||||
"%s %s%s%s %u "
|
||||
"\"%d%02d%02d "
|
||||
"%02d:%02d:%02d\" "
|
||||
"%u %d\n",
|
||||
Curl_alpnid2str(as->src.alpnid), as->src.host, as->src.port,
|
||||
Curl_alpnid2str(as->dst.alpnid), as->dst.host, as->dst.port,
|
||||
Curl_alpnid2str(as->src.alpnid),
|
||||
src6_pre, as->src.host, src6_post,
|
||||
as->src.port,
|
||||
|
||||
Curl_alpnid2str(as->dst.alpnid),
|
||||
dst6_pre, as->dst.host, dst6_post,
|
||||
as->dst.port,
|
||||
|
||||
stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday,
|
||||
stamp.tm_hour, stamp.tm_min, stamp.tm_sec,
|
||||
as->persist, as->prio);
|
||||
@@ -500,9 +544,21 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
|
||||
if(*p != ':') {
|
||||
/* host name starts here */
|
||||
const char *hostp = p;
|
||||
while(*p && (ISALNUM(*p) || (*p == '.') || (*p == '-')))
|
||||
p++;
|
||||
len = p - hostp;
|
||||
if(*p == '[') {
|
||||
/* pass all valid IPv6 letters - does not handle zone id */
|
||||
len = strspn(++p, "0123456789abcdefABCDEF:.");
|
||||
if(p[len] != ']')
|
||||
/* invalid host syntax, bail out */
|
||||
break;
|
||||
/* we store the IPv6 numerical address *with* brackets */
|
||||
len += 2;
|
||||
p = &p[len-1];
|
||||
}
|
||||
else {
|
||||
while(*p && (ISALNUM(*p) || (*p == '.') || (*p == '-')))
|
||||
p++;
|
||||
len = p - hostp;
|
||||
}
|
||||
if(!len || (len >= MAX_ALTSVC_HOSTLEN)) {
|
||||
infof(data, "Excessive alt-svc host name, ignoring.");
|
||||
valid = FALSE;
|
||||
|
||||
@@ -39,4 +39,3 @@ void Curl_amiga_cleanup(void);
|
||||
#endif
|
||||
|
||||
#endif /* HEADER_CURL_AMIGAOS_H */
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ struct thread_data {
|
||||
};
|
||||
|
||||
/* How long we are willing to wait for additional parallel responses after
|
||||
obtaining a "definitive" one.
|
||||
obtaining a "definitive" one. For old c-ares without getaddrinfo.
|
||||
|
||||
This is intended to equal the c-ares default timeout. cURL always uses that
|
||||
default value. Unfortunately, c-ares doesn't expose its default timeout in
|
||||
@@ -120,6 +120,8 @@ struct thread_data {
|
||||
*/
|
||||
#define HAPPY_EYEBALLS_DNS_TIMEOUT 5000
|
||||
|
||||
#define CARES_TIMEOUT_PER_ATTEMPT 2000
|
||||
|
||||
/*
|
||||
* Curl_resolver_global_init() - the generic low-level asynchronous name
|
||||
* resolve API. Called from curl_global_init() to initialize global resolver
|
||||
@@ -173,6 +175,9 @@ CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver)
|
||||
int optmask = ARES_OPT_SOCK_STATE_CB;
|
||||
options.sock_state_cb = sock_state_cb;
|
||||
options.sock_state_cb_data = easy;
|
||||
options.timeout = CARES_TIMEOUT_PER_ATTEMPT;
|
||||
optmask |= ARES_OPT_TIMEOUTMS;
|
||||
|
||||
status = ares_init_options((ares_channel*)resolver, &options, optmask);
|
||||
if(status != ARES_SUCCESS) {
|
||||
if(status == ARES_ENOMEM)
|
||||
@@ -770,9 +775,14 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
|
||||
int pf = PF_INET;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
#ifdef CURLRES_IPV6
|
||||
if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data))
|
||||
if((data->conn->ip_version != CURL_IPRESOLVE_V4) &&
|
||||
Curl_ipv6works(data)) {
|
||||
/* The stack seems to be IPv6-enabled */
|
||||
pf = PF_UNSPEC;
|
||||
if(data->conn->ip_version == CURL_IPRESOLVE_V6)
|
||||
pf = PF_INET6;
|
||||
else
|
||||
pf = PF_UNSPEC;
|
||||
}
|
||||
#endif /* CURLRES_IPV6 */
|
||||
hints.ai_family = pf;
|
||||
hints.ai_socktype = (data->conn->transport == TRNSPRT_TCP)?
|
||||
|
||||
@@ -696,9 +696,13 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
|
||||
*waitp = 0; /* default to synchronous response */
|
||||
|
||||
#ifdef CURLRES_IPV6
|
||||
if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data))
|
||||
if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data)) {
|
||||
/* The stack seems to be IPv6-enabled */
|
||||
pf = PF_UNSPEC;
|
||||
if(data->conn->ip_version == CURL_IPRESOLVE_V6)
|
||||
pf = PF_INET6;
|
||||
else
|
||||
pf = PF_UNSPEC;
|
||||
}
|
||||
#endif /* CURLRES_IPV6 */
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
|
||||
@@ -32,13 +32,14 @@
|
||||
!defined(CURL_DISABLE_POP3) || \
|
||||
!defined(CURL_DISABLE_IMAP) || \
|
||||
!defined(CURL_DISABLE_DOH) || defined(USE_SSL)
|
||||
|
||||
#include "urldata.h" /* for the Curl_easy definition */
|
||||
#include "curl/curl.h"
|
||||
#include "warnless.h"
|
||||
#include "curl_base64.h"
|
||||
|
||||
/* The last 2 #include files should be in this order */
|
||||
#ifdef BUILDING_LIBCURL
|
||||
#include "curl_memory.h"
|
||||
#endif
|
||||
#include "memdebug.h"
|
||||
|
||||
/* ---- Base64 Encoding/Decoding Table --- */
|
||||
|
||||
@@ -61,6 +61,11 @@
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
typedef enum {
|
||||
USERDATA_NOT_SET = 0, /* for tasks with no userdata set; must be zero */
|
||||
USERDATA_RESP_BODY
|
||||
} userdata_t;
|
||||
|
||||
size_t Curl_hyper_recv(void *userp, hyper_context *ctx,
|
||||
uint8_t *buf, size_t buflen)
|
||||
{
|
||||
@@ -182,8 +187,11 @@ static int hyper_each_header(void *userdata,
|
||||
}
|
||||
}
|
||||
|
||||
data->info.header_size += (curl_off_t)len;
|
||||
data->req.headerbytecount += (curl_off_t)len;
|
||||
result = Curl_bump_headersize(data, len, FALSE);
|
||||
if(result) {
|
||||
data->state.hresult = result;
|
||||
return HYPER_ITER_BREAK;
|
||||
}
|
||||
return HYPER_ITER_CONTINUE;
|
||||
}
|
||||
|
||||
@@ -313,9 +321,8 @@ static CURLcode status_line(struct Curl_easy *data,
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
data->info.header_size += (curl_off_t)len;
|
||||
data->req.headerbytecount += (curl_off_t)len;
|
||||
return CURLE_OK;
|
||||
result = Curl_bump_headersize(data, len, FALSE);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -348,7 +355,6 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
|
||||
struct hyptransfer *h = &data->hyp;
|
||||
hyper_task *task;
|
||||
hyper_task *foreach;
|
||||
hyper_error *hypererr = NULL;
|
||||
const uint8_t *reasonp;
|
||||
size_t reason_len;
|
||||
CURLcode result = CURLE_OK;
|
||||
@@ -391,19 +397,9 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
|
||||
break;
|
||||
}
|
||||
t = hyper_task_type(task);
|
||||
switch(t) {
|
||||
case HYPER_TASK_ERROR:
|
||||
hypererr = hyper_task_value(task);
|
||||
break;
|
||||
case HYPER_TASK_RESPONSE:
|
||||
resp = hyper_task_value(task);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
hyper_task_free(task);
|
||||
|
||||
if(t == HYPER_TASK_ERROR) {
|
||||
hyper_error *hypererr = hyper_task_value(task);
|
||||
hyper_task_free(task);
|
||||
if(data->state.hresult) {
|
||||
/* override Hyper's view, might not even be an error */
|
||||
result = data->state.hresult;
|
||||
@@ -414,36 +410,55 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
|
||||
size_t errlen = hyper_error_print(hypererr, errbuf, sizeof(errbuf));
|
||||
hyper_code code = hyper_error_code(hypererr);
|
||||
failf(data, "Hyper: [%d] %.*s", (int)code, (int)errlen, errbuf);
|
||||
if(code == HYPERE_ABORTED_BY_CALLBACK)
|
||||
switch(code) {
|
||||
case HYPERE_ABORTED_BY_CALLBACK:
|
||||
result = CURLE_OK;
|
||||
else if((code == HYPERE_UNEXPECTED_EOF) && !data->req.bytecount)
|
||||
result = CURLE_GOT_NOTHING;
|
||||
else if(code == HYPERE_INVALID_PEER_MESSAGE)
|
||||
break;
|
||||
case HYPERE_UNEXPECTED_EOF:
|
||||
if(!data->req.bytecount)
|
||||
result = CURLE_GOT_NOTHING;
|
||||
else
|
||||
result = CURLE_RECV_ERROR;
|
||||
break;
|
||||
case HYPERE_INVALID_PEER_MESSAGE:
|
||||
/* bump headerbytecount to avoid the count remaining at zero and
|
||||
appearing to not having read anything from the peer at all */
|
||||
data->req.headerbytecount++;
|
||||
result = CURLE_UNSUPPORTED_PROTOCOL; /* maybe */
|
||||
else
|
||||
break;
|
||||
default:
|
||||
result = CURLE_RECV_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*done = TRUE;
|
||||
hyper_error_free(hypererr);
|
||||
break;
|
||||
}
|
||||
else if(h->endtask == task) {
|
||||
/* end of transfer, forget the task handled, we might get a
|
||||
* new one with the same address in the future. */
|
||||
*done = TRUE;
|
||||
h->endtask = NULL;
|
||||
infof(data, "hyperstream is done");
|
||||
if(!k->bodywrites) {
|
||||
/* hyper doesn't always call the body write callback */
|
||||
bool stilldone;
|
||||
result = Curl_http_firstwrite(data, data->conn, &stilldone);
|
||||
else if(t == HYPER_TASK_EMPTY) {
|
||||
void *userdata = hyper_task_userdata(task);
|
||||
hyper_task_free(task);
|
||||
if((userdata_t)userdata == USERDATA_RESP_BODY) {
|
||||
/* end of transfer */
|
||||
*done = TRUE;
|
||||
infof(data, "hyperstream is done");
|
||||
if(!k->bodywrites) {
|
||||
/* hyper doesn't always call the body write callback */
|
||||
bool stilldone;
|
||||
result = Curl_http_firstwrite(data, data->conn, &stilldone);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else {
|
||||
/* A background task for hyper; ignore */
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if(t != HYPER_TASK_RESPONSE) {
|
||||
continue;
|
||||
}
|
||||
/* HYPER_TASK_RESPONSE */
|
||||
|
||||
DEBUGASSERT(HYPER_TASK_RESPONSE);
|
||||
|
||||
resp = hyper_task_value(task);
|
||||
hyper_task_free(task);
|
||||
|
||||
*didwhat = KEEP_RECV;
|
||||
if(!resp) {
|
||||
@@ -523,13 +538,12 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
break;
|
||||
}
|
||||
DEBUGASSERT(hyper_task_type(foreach) == HYPER_TASK_EMPTY);
|
||||
hyper_task_set_userdata(foreach, (void *)USERDATA_RESP_BODY);
|
||||
if(HYPERE_OK != hyper_executor_push(h->exec, foreach)) {
|
||||
failf(data, "Couldn't hyper_executor_push the body-foreach");
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
break;
|
||||
}
|
||||
h->endtask = foreach;
|
||||
|
||||
hyper_response_free(resp);
|
||||
resp = NULL;
|
||||
@@ -757,7 +771,7 @@ static int uploadstreamed(void *userdata, hyper_context *ctx,
|
||||
/* increasing the writebytecount here is a little premature but we
|
||||
don't know exactly when the body is sent */
|
||||
data->req.writebytecount += fillcount;
|
||||
Curl_pgrsSetUploadCounter(data, fillcount);
|
||||
Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
|
||||
}
|
||||
return HYPER_POLL_READY;
|
||||
}
|
||||
@@ -794,15 +808,16 @@ static CURLcode bodysend(struct Curl_easy *data,
|
||||
hyper_body_set_data_func(body, uploadpostfields);
|
||||
else {
|
||||
result = Curl_get_upload_buffer(data);
|
||||
if(result)
|
||||
if(result) {
|
||||
hyper_body_free(body);
|
||||
return result;
|
||||
}
|
||||
/* init the "upload from here" pointer */
|
||||
data->req.upload_fromhere = data->state.ulbuf;
|
||||
hyper_body_set_data_func(body, uploadstreamed);
|
||||
}
|
||||
if(HYPERE_OK != hyper_request_set_body(hyperreq, body)) {
|
||||
/* fail */
|
||||
hyper_body_free(body);
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
@@ -1194,14 +1209,17 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto error;
|
||||
}
|
||||
req = NULL;
|
||||
|
||||
if(HYPERE_OK != hyper_executor_push(h->exec, sendtask)) {
|
||||
failf(data, "Couldn't hyper_executor_push the send");
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto error;
|
||||
}
|
||||
sendtask = NULL; /* ownership passed on */
|
||||
|
||||
hyper_clientconn_free(client);
|
||||
client = NULL;
|
||||
|
||||
if((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) {
|
||||
/* HTTP GET/HEAD download */
|
||||
@@ -1214,8 +1232,8 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
|
||||
the full request has been sent. */
|
||||
data->req.start100 = Curl_now();
|
||||
|
||||
/* clear userpwd and proxyuserpwd to avoid re-using old credentials
|
||||
* from re-used connections */
|
||||
/* clear userpwd and proxyuserpwd to avoid reusing old credentials
|
||||
* from reused connections */
|
||||
Curl_safefree(data->state.aptr.userpwd);
|
||||
Curl_safefree(data->state.aptr.proxyuserpwd);
|
||||
return CURLE_OK;
|
||||
@@ -1230,6 +1248,12 @@ error:
|
||||
if(handshake)
|
||||
hyper_task_free(handshake);
|
||||
|
||||
if(client)
|
||||
hyper_clientconn_free(client);
|
||||
|
||||
if(req)
|
||||
hyper_request_free(req);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@ struct hyptransfer {
|
||||
hyper_waker *write_waker;
|
||||
hyper_waker *read_waker;
|
||||
const hyper_executor *exec;
|
||||
hyper_task *endtask;
|
||||
hyper_waker *exp100_waker;
|
||||
hyper_waker *send_body_waker;
|
||||
};
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
#include "cfilters.h"
|
||||
#include "cf-h1-proxy.h"
|
||||
#include "connect.h"
|
||||
#include "curl_log.h"
|
||||
#include "curl_trc.h"
|
||||
#include "curlx.h"
|
||||
#include "vtls/vtls.h"
|
||||
#include "transfer.h"
|
||||
@@ -175,36 +175,36 @@ static void h1_tunnel_go_state(struct Curl_cfilter *cf,
|
||||
/* entering this one */
|
||||
switch(new_state) {
|
||||
case H1_TUNNEL_INIT:
|
||||
DEBUGF(LOG_CF(data, cf, "new tunnel state 'init'"));
|
||||
CURL_TRC_CF(data, cf, "new tunnel state 'init'");
|
||||
tunnel_reinit(ts, cf->conn, data);
|
||||
break;
|
||||
|
||||
case H1_TUNNEL_CONNECT:
|
||||
DEBUGF(LOG_CF(data, cf, "new tunnel state 'connect'"));
|
||||
CURL_TRC_CF(data, cf, "new tunnel state 'connect'");
|
||||
ts->tunnel_state = H1_TUNNEL_CONNECT;
|
||||
ts->keepon = KEEPON_CONNECT;
|
||||
Curl_dyn_reset(&ts->rcvbuf);
|
||||
break;
|
||||
|
||||
case H1_TUNNEL_RECEIVE:
|
||||
DEBUGF(LOG_CF(data, cf, "new tunnel state 'receive'"));
|
||||
CURL_TRC_CF(data, cf, "new tunnel state 'receive'");
|
||||
ts->tunnel_state = H1_TUNNEL_RECEIVE;
|
||||
break;
|
||||
|
||||
case H1_TUNNEL_RESPONSE:
|
||||
DEBUGF(LOG_CF(data, cf, "new tunnel state 'response'"));
|
||||
CURL_TRC_CF(data, cf, "new tunnel state 'response'");
|
||||
ts->tunnel_state = H1_TUNNEL_RESPONSE;
|
||||
break;
|
||||
|
||||
case H1_TUNNEL_ESTABLISHED:
|
||||
DEBUGF(LOG_CF(data, cf, "new tunnel state 'established'"));
|
||||
CURL_TRC_CF(data, cf, "new tunnel state 'established'");
|
||||
infof(data, "CONNECT phase completed");
|
||||
data->state.authproxy.done = TRUE;
|
||||
data->state.authproxy.multipass = FALSE;
|
||||
/* FALLTHROUGH */
|
||||
case H1_TUNNEL_FAILED:
|
||||
if(new_state == H1_TUNNEL_FAILED)
|
||||
DEBUGF(LOG_CF(data, cf, "new tunnel state 'failed'"));
|
||||
CURL_TRC_CF(data, cf, "new tunnel state 'failed'");
|
||||
ts->tunnel_state = new_state;
|
||||
Curl_dyn_reset(&ts->rcvbuf);
|
||||
Curl_dyn_reset(&ts->req);
|
||||
@@ -416,7 +416,7 @@ static CURLcode on_resp_header(struct Curl_cfilter *cf,
|
||||
if(!auth)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
DEBUGF(LOG_CF(data, cf, "CONNECT: fwd auth header '%s'", header));
|
||||
CURL_TRC_CF(data, cf, "CONNECT: fwd auth header '%s'", header);
|
||||
result = Curl_http_input_auth(data, proxy, auth);
|
||||
|
||||
free(auth);
|
||||
@@ -587,7 +587,9 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
|
||||
return result;
|
||||
}
|
||||
|
||||
data->info.header_size += (long)perline;
|
||||
result = Curl_bump_headersize(data, perline, TRUE);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
/* Newlines are CRLF, so the CR is ignored as the line isn't
|
||||
really terminated until the LF comes. Treat a following CR
|
||||
@@ -636,7 +638,7 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
|
||||
/* without content-length or chunked encoding, we
|
||||
can't keep the connection alive since the close is
|
||||
the end signal so we bail out at once instead */
|
||||
DEBUGF(LOG_CF(data, cf, "CONNECT: no content-length or chunked"));
|
||||
CURL_TRC_CF(data, cf, "CONNECT: no content-length or chunked");
|
||||
ts->keepon = KEEPON_DONE;
|
||||
}
|
||||
}
|
||||
@@ -713,14 +715,13 @@ static CURLcode start_CONNECT(struct Curl_cfilter *cf,
|
||||
}
|
||||
|
||||
options = hyper_clientconn_options_new();
|
||||
hyper_clientconn_options_set_preserve_header_case(options, 1);
|
||||
hyper_clientconn_options_set_preserve_header_order(options, 1);
|
||||
|
||||
if(!options) {
|
||||
failf(data, "Couldn't create hyper client options");
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto error;
|
||||
}
|
||||
hyper_clientconn_options_set_preserve_header_case(options, 1);
|
||||
hyper_clientconn_options_set_preserve_header_order(options, 1);
|
||||
|
||||
hyper_clientconn_options_exec(options, h->exec);
|
||||
|
||||
@@ -751,6 +752,7 @@ static CURLcode start_CONNECT(struct Curl_cfilter *cf,
|
||||
|
||||
client = hyper_task_value(task);
|
||||
hyper_task_free(task);
|
||||
|
||||
req = hyper_request_new();
|
||||
if(!req) {
|
||||
failf(data, "Couldn't hyper_request_new");
|
||||
@@ -859,12 +861,17 @@ static CURLcode start_CONNECT(struct Curl_cfilter *cf,
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto error;
|
||||
}
|
||||
req = NULL;
|
||||
|
||||
if(HYPERE_OK != hyper_executor_push(h->exec, sendtask)) {
|
||||
failf(data, "Couldn't hyper_executor_push the send");
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto error;
|
||||
}
|
||||
sendtask = NULL; /* ownership passed on */
|
||||
|
||||
hyper_clientconn_free(client);
|
||||
client = NULL;
|
||||
|
||||
error:
|
||||
free(host);
|
||||
@@ -877,6 +884,9 @@ error:
|
||||
hyper_task_free(handshake);
|
||||
if(client)
|
||||
hyper_clientconn_free(client);
|
||||
if(req)
|
||||
hyper_request_free(req);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -975,7 +985,7 @@ static CURLcode H1_CONNECT(struct Curl_cfilter *cf,
|
||||
switch(ts->tunnel_state) {
|
||||
case H1_TUNNEL_INIT:
|
||||
/* Prepare the CONNECT request and make a first attempt to send. */
|
||||
DEBUGF(LOG_CF(data, cf, "CONNECT start"));
|
||||
CURL_TRC_CF(data, cf, "CONNECT start");
|
||||
result = start_CONNECT(cf, data, ts);
|
||||
if(result)
|
||||
goto out;
|
||||
@@ -984,7 +994,7 @@ static CURLcode H1_CONNECT(struct Curl_cfilter *cf,
|
||||
|
||||
case H1_TUNNEL_CONNECT:
|
||||
/* see that the request is completely sent */
|
||||
DEBUGF(LOG_CF(data, cf, "CONNECT send"));
|
||||
CURL_TRC_CF(data, cf, "CONNECT send");
|
||||
result = send_CONNECT(data, cf->conn, ts, &done);
|
||||
if(result || !done)
|
||||
goto out;
|
||||
@@ -993,7 +1003,7 @@ static CURLcode H1_CONNECT(struct Curl_cfilter *cf,
|
||||
|
||||
case H1_TUNNEL_RECEIVE:
|
||||
/* read what is there */
|
||||
DEBUGF(LOG_CF(data, cf, "CONNECT receive"));
|
||||
CURL_TRC_CF(data, cf, "CONNECT receive");
|
||||
result = recv_CONNECT_resp(cf, data, ts, &done);
|
||||
if(Curl_pgrsUpdate(data)) {
|
||||
result = CURLE_ABORTED_BY_CALLBACK;
|
||||
@@ -1007,7 +1017,7 @@ static CURLcode H1_CONNECT(struct Curl_cfilter *cf,
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case H1_TUNNEL_RESPONSE:
|
||||
DEBUGF(LOG_CF(data, cf, "CONNECT response"));
|
||||
CURL_TRC_CF(data, cf, "CONNECT response");
|
||||
if(data->req.newurl) {
|
||||
/* not the "final" response, we need to do a follow up request.
|
||||
* If the other side indicated a connection close, or if someone
|
||||
@@ -1019,7 +1029,7 @@ static CURLcode H1_CONNECT(struct Curl_cfilter *cf,
|
||||
* reset our tunnel state. To avoid recursion, we return
|
||||
* and expect to be called again.
|
||||
*/
|
||||
DEBUGF(LOG_CF(data, cf, "CONNECT need to close+open"));
|
||||
CURL_TRC_CF(data, cf, "CONNECT need to close+open");
|
||||
infof(data, "Connect me again please");
|
||||
Curl_conn_cf_close(cf, data);
|
||||
connkeep(conn, "HTTP proxy CONNECT");
|
||||
@@ -1043,7 +1053,7 @@ static CURLcode H1_CONNECT(struct Curl_cfilter *cf,
|
||||
if(data->info.httpproxycode/100 != 2) {
|
||||
/* a non-2xx response and we have no next url to try. */
|
||||
Curl_safefree(data->req.newurl);
|
||||
/* failure, close this connection to avoid re-use */
|
||||
/* failure, close this connection to avoid reuse */
|
||||
streamclose(conn, "proxy CONNECT failure");
|
||||
h1_tunnel_go_state(cf, ts, H1_TUNNEL_FAILED, data);
|
||||
failf(data, "CONNECT tunnel failed, response %d", data->req.httpcode);
|
||||
@@ -1073,7 +1083,7 @@ static CURLcode cf_h1_proxy_connect(struct Curl_cfilter *cf,
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
DEBUGF(LOG_CF(data, cf, "connect"));
|
||||
CURL_TRC_CF(data, cf, "connect");
|
||||
result = cf->next->cft->do_connect(cf->next, data, blocking, done);
|
||||
if(result || !*done)
|
||||
return result;
|
||||
@@ -1133,14 +1143,14 @@ static int cf_h1_proxy_get_select_socks(struct Curl_cfilter *cf,
|
||||
static void cf_h1_proxy_destroy(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
DEBUGF(LOG_CF(data, cf, "destroy"));
|
||||
CURL_TRC_CF(data, cf, "destroy");
|
||||
tunnel_free(cf, data);
|
||||
}
|
||||
|
||||
static void cf_h1_proxy_close(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
DEBUGF(LOG_CF(data, cf, "close"));
|
||||
CURL_TRC_CF(data, cf, "close");
|
||||
cf->connected = FALSE;
|
||||
if(cf->ctx) {
|
||||
h1_tunnel_go_state(cf, cf->ctx, H1_TUNNEL_INIT, data);
|
||||
|
||||
+252
-122
@@ -30,11 +30,12 @@
|
||||
#include "urldata.h"
|
||||
#include "cfilters.h"
|
||||
#include "connect.h"
|
||||
#include "curl_log.h"
|
||||
#include "curl_trc.h"
|
||||
#include "bufq.h"
|
||||
#include "dynbuf.h"
|
||||
#include "dynhds.h"
|
||||
#include "http1.h"
|
||||
#include "http2.h"
|
||||
#include "http_proxy.h"
|
||||
#include "multiif.h"
|
||||
#include "cf-h2-proxy.h"
|
||||
@@ -44,16 +45,16 @@
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
#define H2_CHUNK_SIZE (16*1024)
|
||||
#define PROXY_H2_CHUNK_SIZE (16*1024)
|
||||
|
||||
#define PROXY_HTTP2_HUGE_WINDOW_SIZE (100 * 1024 * 1024)
|
||||
#define H2_TUNNEL_WINDOW_SIZE (10 * 1024 * 1024)
|
||||
|
||||
#define PROXY_H2_NW_RECV_CHUNKS (H2_TUNNEL_WINDOW_SIZE / H2_CHUNK_SIZE)
|
||||
#define PROXY_H2_NW_RECV_CHUNKS (H2_TUNNEL_WINDOW_SIZE / PROXY_H2_CHUNK_SIZE)
|
||||
#define PROXY_H2_NW_SEND_CHUNKS 1
|
||||
|
||||
#define H2_TUNNEL_RECV_CHUNKS (H2_TUNNEL_WINDOW_SIZE / H2_CHUNK_SIZE)
|
||||
#define H2_TUNNEL_SEND_CHUNKS ((128 * 1024) / H2_CHUNK_SIZE)
|
||||
#define H2_TUNNEL_RECV_CHUNKS (H2_TUNNEL_WINDOW_SIZE / PROXY_H2_CHUNK_SIZE)
|
||||
#define H2_TUNNEL_SEND_CHUNKS ((128 * 1024) / PROXY_H2_CHUNK_SIZE)
|
||||
|
||||
|
||||
typedef enum {
|
||||
@@ -87,9 +88,9 @@ static CURLcode tunnel_stream_init(struct Curl_cfilter *cf,
|
||||
|
||||
ts->state = H2_TUNNEL_INIT;
|
||||
ts->stream_id = -1;
|
||||
Curl_bufq_init2(&ts->recvbuf, H2_CHUNK_SIZE, H2_TUNNEL_RECV_CHUNKS,
|
||||
Curl_bufq_init2(&ts->recvbuf, PROXY_H2_CHUNK_SIZE, H2_TUNNEL_RECV_CHUNKS,
|
||||
BUFQ_OPT_SOFT_LIMIT);
|
||||
Curl_bufq_init(&ts->sendbuf, H2_CHUNK_SIZE, H2_TUNNEL_SEND_CHUNKS);
|
||||
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;
|
||||
@@ -146,29 +147,30 @@ static void h2_tunnel_go_state(struct Curl_cfilter *cf,
|
||||
/* entering this one */
|
||||
switch(new_state) {
|
||||
case H2_TUNNEL_INIT:
|
||||
DEBUGF(LOG_CF(data, cf, "new tunnel state 'init'"));
|
||||
CURL_TRC_CF(data, cf, "[%d] new tunnel state 'init'", ts->stream_id);
|
||||
tunnel_stream_clear(ts);
|
||||
break;
|
||||
|
||||
case H2_TUNNEL_CONNECT:
|
||||
DEBUGF(LOG_CF(data, cf, "new tunnel state 'connect'"));
|
||||
CURL_TRC_CF(data, cf, "[%d] new tunnel state 'connect'", ts->stream_id);
|
||||
ts->state = H2_TUNNEL_CONNECT;
|
||||
break;
|
||||
|
||||
case H2_TUNNEL_RESPONSE:
|
||||
DEBUGF(LOG_CF(data, cf, "new tunnel state 'response'"));
|
||||
CURL_TRC_CF(data, cf, "[%d] new tunnel state 'response'", ts->stream_id);
|
||||
ts->state = H2_TUNNEL_RESPONSE;
|
||||
break;
|
||||
|
||||
case H2_TUNNEL_ESTABLISHED:
|
||||
DEBUGF(LOG_CF(data, cf, "new tunnel state 'established'"));
|
||||
CURL_TRC_CF(data, cf, "[%d] new tunnel state 'established'",
|
||||
ts->stream_id);
|
||||
infof(data, "CONNECT phase completed");
|
||||
data->state.authproxy.done = TRUE;
|
||||
data->state.authproxy.multipass = FALSE;
|
||||
/* FALLTHROUGH */
|
||||
case H2_TUNNEL_FAILED:
|
||||
if(new_state == H2_TUNNEL_FAILED)
|
||||
DEBUGF(LOG_CF(data, cf, "new tunnel state 'failed'"));
|
||||
CURL_TRC_CF(data, cf, "[%d] new tunnel state 'failed'", ts->stream_id);
|
||||
ts->state = new_state;
|
||||
/* If a proxy-authorization header was used for the proxy, then we should
|
||||
make sure that it isn't accidentally used for the document request
|
||||
@@ -231,9 +233,9 @@ 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) {
|
||||
DEBUGF(LOG_CF(data, cf, "[h2sid=%d] DRAIN dselect_bits=%x",
|
||||
tunnel->stream_id, bits));
|
||||
if(data->state.dselect_bits != bits || 1) {
|
||||
CURL_TRC_CF(data, cf, "[%d] DRAIN dselect_bits=%x",
|
||||
tunnel->stream_id, bits);
|
||||
data->state.dselect_bits = bits;
|
||||
Curl_expire(data, 0, EXPIRE_RUN_NOW);
|
||||
}
|
||||
@@ -244,12 +246,17 @@ static ssize_t proxy_nw_in_reader(void *reader_ctx,
|
||||
CURLcode *err)
|
||||
{
|
||||
struct Curl_cfilter *cf = reader_ctx;
|
||||
struct Curl_easy *data = CF_DATA_CURRENT(cf);
|
||||
ssize_t nread;
|
||||
|
||||
nread = Curl_conn_cf_recv(cf->next, data, (char *)buf, buflen, err);
|
||||
DEBUGF(LOG_CF(data, cf, "nw_in_reader(len=%zu) -> %zd, %d",
|
||||
buflen, nread, *err));
|
||||
if(cf) {
|
||||
struct Curl_easy *data = CF_DATA_CURRENT(cf);
|
||||
nread = Curl_conn_cf_recv(cf->next, data, (char *)buf, buflen, err);
|
||||
CURL_TRC_CF(data, cf, "[0] nw_in_reader(len=%zu) -> %zd, %d",
|
||||
buflen, nread, *err);
|
||||
}
|
||||
else {
|
||||
nread = 0;
|
||||
}
|
||||
return nread;
|
||||
}
|
||||
|
||||
@@ -258,12 +265,18 @@ static ssize_t proxy_h2_nw_out_writer(void *writer_ctx,
|
||||
CURLcode *err)
|
||||
{
|
||||
struct Curl_cfilter *cf = writer_ctx;
|
||||
struct Curl_easy *data = CF_DATA_CURRENT(cf);
|
||||
ssize_t nwritten;
|
||||
|
||||
nwritten = Curl_conn_cf_send(cf->next, data, (const char *)buf, buflen, err);
|
||||
DEBUGF(LOG_CF(data, cf, "nw_out_writer(len=%zu) -> %zd, %d",
|
||||
buflen, nwritten, *err));
|
||||
if(cf) {
|
||||
struct Curl_easy *data = CF_DATA_CURRENT(cf);
|
||||
nwritten = Curl_conn_cf_send(cf->next, data, (const char *)buf, buflen,
|
||||
err);
|
||||
CURL_TRC_CF(data, cf, "[0] nw_out_writer(len=%zu) -> %zd, %d",
|
||||
buflen, nwritten, *err);
|
||||
}
|
||||
else {
|
||||
nwritten = 0;
|
||||
}
|
||||
return nwritten;
|
||||
}
|
||||
|
||||
@@ -295,6 +308,10 @@ static ssize_t on_session_send(nghttp2_session *h2,
|
||||
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);
|
||||
#endif
|
||||
static int proxy_h2_on_stream_close(nghttp2_session *session,
|
||||
int32_t stream_id,
|
||||
uint32_t error_code, void *userp);
|
||||
@@ -322,8 +339,8 @@ static CURLcode cf_h2_proxy_ctx_init(struct Curl_cfilter *cf,
|
||||
DEBUGASSERT(!ctx->h2);
|
||||
memset(&ctx->tunnel, 0, sizeof(ctx->tunnel));
|
||||
|
||||
Curl_bufq_init(&ctx->inbufq, H2_CHUNK_SIZE, PROXY_H2_NW_RECV_CHUNKS);
|
||||
Curl_bufq_init(&ctx->outbufq, H2_CHUNK_SIZE, PROXY_H2_NW_SEND_CHUNKS);
|
||||
Curl_bufq_init(&ctx->inbufq, PROXY_H2_CHUNK_SIZE, PROXY_H2_NW_RECV_CHUNKS);
|
||||
Curl_bufq_init(&ctx->outbufq, PROXY_H2_CHUNK_SIZE, PROXY_H2_NW_SEND_CHUNKS);
|
||||
|
||||
if(tunnel_stream_init(cf, &ctx->tunnel))
|
||||
goto out;
|
||||
@@ -337,6 +354,9 @@ static CURLcode cf_h2_proxy_ctx_init(struct Curl_cfilter *cf,
|
||||
nghttp2_session_callbacks_set_send_callback(cbs, on_session_send);
|
||||
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);
|
||||
#endif
|
||||
nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
|
||||
cbs, tunnel_recv_callback);
|
||||
nghttp2_session_callbacks_set_on_stream_close_callback(
|
||||
@@ -384,11 +404,11 @@ static CURLcode cf_h2_proxy_ctx_init(struct Curl_cfilter *cf,
|
||||
out:
|
||||
if(cbs)
|
||||
nghttp2_session_callbacks_del(cbs);
|
||||
DEBUGF(LOG_CF(data, cf, "init proxy ctx -> %d", result));
|
||||
CURL_TRC_CF(data, cf, "[0] init proxy ctx -> %d", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int should_close_session(struct cf_h2_proxy_ctx *ctx)
|
||||
static int proxy_h2_should_close_session(struct cf_h2_proxy_ctx *ctx)
|
||||
{
|
||||
return !nghttp2_session_want_read(ctx->h2) &&
|
||||
!nghttp2_session_want_write(ctx->h2);
|
||||
@@ -409,13 +429,13 @@ static CURLcode proxy_h2_nw_out_flush(struct Curl_cfilter *cf,
|
||||
&result);
|
||||
if(nwritten < 0) {
|
||||
if(result == CURLE_AGAIN) {
|
||||
DEBUGF(LOG_CF(data, cf, "flush nw send buffer(%zu) -> EAGAIN",
|
||||
Curl_bufq_len(&ctx->outbufq)));
|
||||
CURL_TRC_CF(data, cf, "[0] flush nw send buffer(%zu) -> EAGAIN",
|
||||
Curl_bufq_len(&ctx->outbufq));
|
||||
ctx->nw_out_blocked = 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
DEBUGF(LOG_CF(data, cf, "nw send buffer flushed"));
|
||||
CURL_TRC_CF(data, cf, "[0] nw send buffer flushed");
|
||||
return Curl_bufq_is_empty(&ctx->outbufq)? CURLE_OK: CURLE_AGAIN;
|
||||
}
|
||||
|
||||
@@ -436,8 +456,7 @@ static int proxy_h2_process_pending_input(struct Curl_cfilter *cf,
|
||||
while(Curl_bufq_peek(&ctx->inbufq, &buf, &blen)) {
|
||||
|
||||
rv = nghttp2_session_mem_recv(ctx->h2, (const uint8_t *)buf, blen);
|
||||
DEBUGF(LOG_CF(data, cf,
|
||||
"fed %zu bytes from nw to nghttp2 -> %zd", blen, rv));
|
||||
CURL_TRC_CF(data, cf, "[0] %zu bytes to nghttp2 -> %zd", blen, rv);
|
||||
if(rv < 0) {
|
||||
failf(data,
|
||||
"process_pending_input: nghttp2_session_mem_recv() returned "
|
||||
@@ -447,12 +466,12 @@ static int proxy_h2_process_pending_input(struct Curl_cfilter *cf,
|
||||
}
|
||||
Curl_bufq_skip(&ctx->inbufq, (size_t)rv);
|
||||
if(Curl_bufq_is_empty(&ctx->inbufq)) {
|
||||
DEBUGF(LOG_CF(data, cf, "all data in connection buffer processed"));
|
||||
CURL_TRC_CF(data, cf, "[0] all data in connection buffer processed");
|
||||
break;
|
||||
}
|
||||
else {
|
||||
DEBUGF(LOG_CF(data, cf, "process_pending_input: %zu bytes left "
|
||||
"in connection buffer", Curl_bufq_len(&ctx->inbufq)));
|
||||
CURL_TRC_CF(data, cf, "[0] process_pending_input: %zu bytes left "
|
||||
"in connection buffer", Curl_bufq_len(&ctx->inbufq));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -468,8 +487,8 @@ static CURLcode proxy_h2_progress_ingress(struct Curl_cfilter *cf,
|
||||
|
||||
/* Process network input buffer fist */
|
||||
if(!Curl_bufq_is_empty(&ctx->inbufq)) {
|
||||
DEBUGF(LOG_CF(data, cf, "Process %zu bytes in connection buffer",
|
||||
Curl_bufq_len(&ctx->inbufq)));
|
||||
CURL_TRC_CF(data, cf, "[0] process %zu bytes in connection buffer",
|
||||
Curl_bufq_len(&ctx->inbufq));
|
||||
if(proxy_h2_process_pending_input(cf, data, &result) < 0)
|
||||
return result;
|
||||
}
|
||||
@@ -482,8 +501,8 @@ static CURLcode proxy_h2_progress_ingress(struct Curl_cfilter *cf,
|
||||
!Curl_bufq_is_full(&ctx->tunnel.recvbuf)) {
|
||||
|
||||
nread = Curl_bufq_slurp(&ctx->inbufq, proxy_nw_in_reader, cf, &result);
|
||||
DEBUGF(LOG_CF(data, cf, "read %zu bytes nw data -> %zd, %d",
|
||||
Curl_bufq_len(&ctx->inbufq), nread, result));
|
||||
CURL_TRC_CF(data, cf, "[0] read %zu bytes nw data -> %zd, %d",
|
||||
Curl_bufq_len(&ctx->inbufq), nread, result);
|
||||
if(nread < 0) {
|
||||
if(result != CURLE_AGAIN) {
|
||||
failf(data, "Failed receiving HTTP2 data");
|
||||
@@ -518,8 +537,8 @@ static CURLcode proxy_h2_progress_egress(struct Curl_cfilter *cf,
|
||||
rv = nghttp2_session_send(ctx->h2);
|
||||
|
||||
if(nghttp2_is_fatal(rv)) {
|
||||
DEBUGF(LOG_CF(data, cf, "nghttp2_session_send error (%s)%d",
|
||||
nghttp2_strerror(rv), rv));
|
||||
CURL_TRC_CF(data, cf, "[0] nghttp2_session_send error (%s)%d",
|
||||
nghttp2_strerror(rv), rv);
|
||||
return CURLE_SEND_ERROR;
|
||||
}
|
||||
return proxy_h2_nw_out_flush(cf, data);
|
||||
@@ -555,6 +574,97 @@ static ssize_t on_session_send(nghttp2_session *h2,
|
||||
return nwritten;
|
||||
}
|
||||
|
||||
#ifndef CURL_DISABLE_VERBOSE_STRINGS
|
||||
static int fr_print(const nghttp2_frame *frame, char *buffer, size_t blen)
|
||||
{
|
||||
switch(frame->hd.type) {
|
||||
case NGHTTP2_DATA: {
|
||||
return msnprintf(buffer, blen,
|
||||
"FRAME[DATA, len=%d, eos=%d, padlen=%d]",
|
||||
(int)frame->hd.length,
|
||||
!!(frame->hd.flags & NGHTTP2_FLAG_END_STREAM),
|
||||
(int)frame->data.padlen);
|
||||
}
|
||||
case NGHTTP2_HEADERS: {
|
||||
return msnprintf(buffer, blen,
|
||||
"FRAME[HEADERS, len=%d, hend=%d, eos=%d]",
|
||||
(int)frame->hd.length,
|
||||
!!(frame->hd.flags & NGHTTP2_FLAG_END_HEADERS),
|
||||
!!(frame->hd.flags & NGHTTP2_FLAG_END_STREAM));
|
||||
}
|
||||
case NGHTTP2_PRIORITY: {
|
||||
return msnprintf(buffer, blen,
|
||||
"FRAME[PRIORITY, len=%d, flags=%d]",
|
||||
(int)frame->hd.length, frame->hd.flags);
|
||||
}
|
||||
case NGHTTP2_RST_STREAM: {
|
||||
return msnprintf(buffer, blen,
|
||||
"FRAME[RST_STREAM, len=%d, flags=%d, error=%u]",
|
||||
(int)frame->hd.length, frame->hd.flags,
|
||||
frame->rst_stream.error_code);
|
||||
}
|
||||
case NGHTTP2_SETTINGS: {
|
||||
if(frame->hd.flags & NGHTTP2_FLAG_ACK) {
|
||||
return msnprintf(buffer, blen, "FRAME[SETTINGS, ack=1]");
|
||||
}
|
||||
return msnprintf(buffer, blen,
|
||||
"FRAME[SETTINGS, len=%d]", (int)frame->hd.length);
|
||||
}
|
||||
case NGHTTP2_PUSH_PROMISE: {
|
||||
return msnprintf(buffer, blen,
|
||||
"FRAME[PUSH_PROMISE, len=%d, hend=%d]",
|
||||
(int)frame->hd.length,
|
||||
!!(frame->hd.flags & NGHTTP2_FLAG_END_HEADERS));
|
||||
}
|
||||
case NGHTTP2_PING: {
|
||||
return msnprintf(buffer, blen,
|
||||
"FRAME[PING, len=%d, ack=%d]",
|
||||
(int)frame->hd.length,
|
||||
frame->hd.flags&NGHTTP2_FLAG_ACK);
|
||||
}
|
||||
case NGHTTP2_GOAWAY: {
|
||||
char scratch[128];
|
||||
size_t s_len = sizeof(scratch)/sizeof(scratch[0]);
|
||||
size_t len = (frame->goaway.opaque_data_len < s_len)?
|
||||
frame->goaway.opaque_data_len : s_len-1;
|
||||
if(len)
|
||||
memcpy(scratch, frame->goaway.opaque_data, len);
|
||||
scratch[len] = '\0';
|
||||
return msnprintf(buffer, blen, "FRAME[GOAWAY, error=%d, reason='%s', "
|
||||
"last_stream=%d]", frame->goaway.error_code,
|
||||
scratch, frame->goaway.last_stream_id);
|
||||
}
|
||||
case NGHTTP2_WINDOW_UPDATE: {
|
||||
return msnprintf(buffer, blen,
|
||||
"FRAME[WINDOW_UPDATE, incr=%d]",
|
||||
frame->window_update.window_size_increment);
|
||||
}
|
||||
default:
|
||||
return msnprintf(buffer, blen, "FRAME[%d, len=%d, flags=%d]",
|
||||
frame->hd.type, (int)frame->hd.length,
|
||||
frame->hd.flags);
|
||||
}
|
||||
}
|
||||
|
||||
static int 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);
|
||||
|
||||
(void)session;
|
||||
DEBUGASSERT(data);
|
||||
if(data && Curl_trc_cf_is_verbose(cf, data)) {
|
||||
char buffer[256];
|
||||
int len;
|
||||
len = fr_print(frame, buffer, sizeof(buffer)-1);
|
||||
buffer[len] = 0;
|
||||
CURL_TRC_CF(data, cf, "[%d] -> %s", frame->hd.stream_id, buffer);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* !CURL_DISABLE_VERBOSE_STRINGS */
|
||||
|
||||
static int proxy_h2_on_frame_recv(nghttp2_session *session,
|
||||
const nghttp2_frame *frame,
|
||||
void *userp)
|
||||
@@ -566,75 +676,74 @@ static int proxy_h2_on_frame_recv(nghttp2_session *session,
|
||||
|
||||
(void)session;
|
||||
DEBUGASSERT(data);
|
||||
#ifndef CURL_DISABLE_VERBOSE_STRINGS
|
||||
if(Curl_trc_cf_is_verbose(cf, data)) {
|
||||
char buffer[256];
|
||||
int len;
|
||||
len = fr_print(frame, buffer, sizeof(buffer)-1);
|
||||
buffer[len] = 0;
|
||||
CURL_TRC_CF(data, cf, "[%d] <- %s",frame->hd.stream_id, buffer);
|
||||
}
|
||||
#endif /* !CURL_DISABLE_VERBOSE_STRINGS */
|
||||
|
||||
if(!stream_id) {
|
||||
/* stream ID zero is for connection-oriented stuff */
|
||||
DEBUGASSERT(data);
|
||||
switch(frame->hd.type) {
|
||||
case NGHTTP2_SETTINGS:
|
||||
/* we do not do anything with this for now */
|
||||
/* Since the initial stream window is 64K, a request might be on HOLD,
|
||||
* due to exhaustion. The (initial) SETTINGS may announce a much larger
|
||||
* window and *assume* that we treat this like a WINDOW_UPDATE. Some
|
||||
* servers send an explicit WINDOW_UPDATE, but not all seem to do that.
|
||||
* To be safe, we UNHOLD a stream in order not to stall. */
|
||||
if((data->req.keepon & KEEP_SEND_HOLD) &&
|
||||
(data->req.keepon & KEEP_SEND)) {
|
||||
data->req.keepon &= ~KEEP_SEND_HOLD;
|
||||
drain_tunnel(cf, data, &ctx->tunnel);
|
||||
CURL_TRC_CF(data, cf, "[%d] un-holding after SETTINGS",
|
||||
stream_id);
|
||||
}
|
||||
break;
|
||||
case NGHTTP2_GOAWAY:
|
||||
infof(data, "recveived GOAWAY, error=%d, last_stream=%u",
|
||||
frame->goaway.error_code, frame->goaway.last_stream_id);
|
||||
ctx->goaway = TRUE;
|
||||
break;
|
||||
case NGHTTP2_WINDOW_UPDATE:
|
||||
DEBUGF(LOG_CF(data, cf, "recv frame WINDOW_UPDATE"));
|
||||
break;
|
||||
default:
|
||||
DEBUGF(LOG_CF(data, cf, "recv frame %x on 0", frame->hd.type));
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(stream_id != ctx->tunnel.stream_id) {
|
||||
DEBUGF(LOG_CF(data, cf, "[h2sid=%u] rcvd FRAME not for tunnel",
|
||||
stream_id));
|
||||
CURL_TRC_CF(data, cf, "[%d] rcvd FRAME not for tunnel", stream_id);
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
}
|
||||
|
||||
switch(frame->hd.type) {
|
||||
case NGHTTP2_DATA:
|
||||
/* If body started on this stream, then receiving DATA is illegal. */
|
||||
DEBUGF(LOG_CF(data, cf, "[h2sid=%u] recv frame DATA", stream_id));
|
||||
break;
|
||||
case NGHTTP2_HEADERS:
|
||||
DEBUGF(LOG_CF(data, cf, "[h2sid=%u] recv frame HEADERS", stream_id));
|
||||
|
||||
/* nghttp2 guarantees that :status is received, and we store it to
|
||||
stream->status_code. Fuzzing has proven this can still be reached
|
||||
without status code having been set. */
|
||||
if(!ctx->tunnel.resp)
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
/* Only final status code signals the end of header */
|
||||
DEBUGF(LOG_CF(data, cf, "[h2sid=%u] got http status: %d",
|
||||
stream_id, ctx->tunnel.resp->status));
|
||||
CURL_TRC_CF(data, cf, "[%d] got http status: %d",
|
||||
stream_id, ctx->tunnel.resp->status);
|
||||
if(!ctx->tunnel.has_final_response) {
|
||||
if(ctx->tunnel.resp->status / 100 != 1) {
|
||||
ctx->tunnel.has_final_response = TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NGHTTP2_PUSH_PROMISE:
|
||||
DEBUGF(LOG_CF(data, cf, "[h2sid=%u] recv PUSH_PROMISE", stream_id));
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
case NGHTTP2_RST_STREAM:
|
||||
DEBUGF(LOG_CF(data, cf, "[h2sid=%u] recv RST", stream_id));
|
||||
ctx->tunnel.reset = TRUE;
|
||||
break;
|
||||
case NGHTTP2_WINDOW_UPDATE:
|
||||
DEBUGF(LOG_CF(data, cf, "[h2sid=%u] recv WINDOW_UPDATE", stream_id));
|
||||
if((data->req.keepon & KEEP_SEND_HOLD) &&
|
||||
(data->req.keepon & KEEP_SEND)) {
|
||||
data->req.keepon &= ~KEEP_SEND_HOLD;
|
||||
Curl_expire(data, 0, EXPIRE_RUN_NOW);
|
||||
DEBUGF(LOG_CF(data, cf, "[h2sid=%u] unpausing after win update",
|
||||
stream_id));
|
||||
CURL_TRC_CF(data, cf, "[%d] unpausing after win update",
|
||||
stream_id);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEBUGF(LOG_CF(data, cf, "[h2sid=%u] recv frame %x",
|
||||
stream_id, frame->hd.type));
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
@@ -658,10 +767,9 @@ static int proxy_h2_on_header(nghttp2_session *session,
|
||||
(void)session;
|
||||
DEBUGASSERT(stream_id); /* should never be a zero stream ID here */
|
||||
if(stream_id != ctx->tunnel.stream_id) {
|
||||
DEBUGF(LOG_CF(data, cf, "[h2sid=%u] header for non-tunnel stream: "
|
||||
"%.*s: %.*s", stream_id,
|
||||
(int)namelen, name,
|
||||
(int)valuelen, value));
|
||||
CURL_TRC_CF(data, cf, "[%d] header for non-tunnel stream: "
|
||||
"%.*s: %.*s", stream_id,
|
||||
(int)namelen, name, (int)valuelen, value);
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
}
|
||||
|
||||
@@ -689,8 +797,8 @@ static int proxy_h2_on_header(nghttp2_session *session,
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
resp->prev = ctx->tunnel.resp;
|
||||
ctx->tunnel.resp = resp;
|
||||
DEBUGF(LOG_CF(data, cf, "[h2sid=%u] status: HTTP/2 %03d",
|
||||
stream_id, ctx->tunnel.resp->status));
|
||||
CURL_TRC_CF(data, cf, "[%d] status: HTTP/2 %03d",
|
||||
stream_id, ctx->tunnel.resp->status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -703,10 +811,8 @@ static int proxy_h2_on_header(nghttp2_session *session,
|
||||
if(result)
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
|
||||
DEBUGF(LOG_CF(data, cf, "[h2sid=%u] header: %.*s: %.*s",
|
||||
stream_id,
|
||||
(int)namelen, name,
|
||||
(int)valuelen, value));
|
||||
CURL_TRC_CF(data, cf, "[%d] header: %.*s: %.*s",
|
||||
stream_id, (int)namelen, name, (int)valuelen, value);
|
||||
|
||||
return 0; /* 0 is successful */
|
||||
}
|
||||
@@ -746,8 +852,8 @@ static ssize_t tunnel_send_callback(nghttp2_session *session,
|
||||
if(ts->closed && Curl_bufq_is_empty(&ts->sendbuf))
|
||||
*data_flags = NGHTTP2_DATA_FLAG_EOF;
|
||||
|
||||
DEBUGF(LOG_CF(data, cf, "[h2sid=%u] tunnel_send_callback -> %zd",
|
||||
ts->stream_id, nread));
|
||||
CURL_TRC_CF(data, cf, "[%d] tunnel_send_callback -> %zd",
|
||||
ts->stream_id, nread);
|
||||
return nread;
|
||||
}
|
||||
|
||||
@@ -791,8 +897,8 @@ static int proxy_h2_on_stream_close(nghttp2_session *session,
|
||||
if(stream_id != ctx->tunnel.stream_id)
|
||||
return 0;
|
||||
|
||||
DEBUGF(LOG_CF(data, cf, "[h2sid=%u] proxy_h2_on_stream_close, %s (err %d)",
|
||||
stream_id, nghttp2_http2_strerror(error_code), error_code));
|
||||
CURL_TRC_CF(data, cf, "[%d] proxy_h2_on_stream_close, %s (err %d)",
|
||||
stream_id, nghttp2_http2_strerror(error_code), error_code);
|
||||
ctx->tunnel.closed = TRUE;
|
||||
ctx->tunnel.error = error_code;
|
||||
|
||||
@@ -910,8 +1016,8 @@ static CURLcode submit_CONNECT(struct Curl_cfilter *cf,
|
||||
result = proxy_h2_submit(&ts->stream_id, cf, data, ctx->h2, req,
|
||||
NULL, ts, tunnel_send_callback, cf);
|
||||
if(result) {
|
||||
DEBUGF(LOG_CF(data, cf, "send: nghttp2_submit_request error (%s)%u",
|
||||
nghttp2_strerror(ts->stream_id), ts->stream_id));
|
||||
CURL_TRC_CF(data, cf, "[%d] send, nghttp2_submit_request error: %s",
|
||||
ts->stream_id, nghttp2_strerror(ts->stream_id));
|
||||
}
|
||||
|
||||
out:
|
||||
@@ -945,8 +1051,8 @@ static CURLcode inspect_response(struct Curl_cfilter *cf,
|
||||
}
|
||||
|
||||
if(auth_reply) {
|
||||
DEBUGF(LOG_CF(data, cf, "CONNECT: fwd auth header '%s'",
|
||||
auth_reply->value));
|
||||
CURL_TRC_CF(data, cf, "[0] CONNECT: fwd auth header '%s'",
|
||||
auth_reply->value);
|
||||
result = Curl_http_input_auth(data, ts->resp->status == 407,
|
||||
auth_reply->value);
|
||||
if(result)
|
||||
@@ -976,7 +1082,7 @@ static CURLcode H2_CONNECT(struct Curl_cfilter *cf,
|
||||
switch(ts->state) {
|
||||
case H2_TUNNEL_INIT:
|
||||
/* Prepare the CONNECT request and make a first attempt to send. */
|
||||
DEBUGF(LOG_CF(data, cf, "CONNECT start for %s", ts->authority));
|
||||
CURL_TRC_CF(data, cf, "[0] CONNECT start for %s", ts->authority);
|
||||
result = submit_CONNECT(cf, data, ts);
|
||||
if(result)
|
||||
goto out;
|
||||
@@ -1143,8 +1249,8 @@ static ssize_t h2_handle_tunnel_close(struct Curl_cfilter *cf,
|
||||
ssize_t rv = 0;
|
||||
|
||||
if(ctx->tunnel.error == NGHTTP2_REFUSED_STREAM) {
|
||||
DEBUGF(LOG_CF(data, cf, "[h2sid=%u] REFUSED_STREAM, try again on a new "
|
||||
"connection", ctx->tunnel.stream_id));
|
||||
CURL_TRC_CF(data, cf, "[%d] REFUSED_STREAM, try again on a new "
|
||||
"connection", ctx->tunnel.stream_id);
|
||||
connclose(cf->conn, "REFUSED_STREAM"); /* don't use this anymore */
|
||||
*err = CURLE_RECV_ERROR; /* trigger Curl_retry_request() later */
|
||||
return -1;
|
||||
@@ -1164,7 +1270,8 @@ static ssize_t h2_handle_tunnel_close(struct Curl_cfilter *cf,
|
||||
|
||||
*err = CURLE_OK;
|
||||
rv = 0;
|
||||
DEBUGF(LOG_CF(data, cf, "handle_tunnel_close -> %zd, %d", rv, *err));
|
||||
CURL_TRC_CF(data, cf, "[%d] handle_tunnel_close -> %zd, %d",
|
||||
ctx->tunnel.stream_id, rv, *err);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -1200,8 +1307,8 @@ static ssize_t tunnel_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
}
|
||||
|
||||
out:
|
||||
DEBUGF(LOG_CF(data, cf, "tunnel_recv(len=%zu) -> %zd, %d",
|
||||
len, nread, *err));
|
||||
CURL_TRC_CF(data, cf, "[%d] tunnel_recv(len=%zu) -> %zd, %d",
|
||||
ctx->tunnel.stream_id, len, nread, *err);
|
||||
return nread;
|
||||
}
|
||||
|
||||
@@ -1229,13 +1336,22 @@ static ssize_t cf_h2_proxy_recv(struct Curl_cfilter *cf,
|
||||
nread = tunnel_recv(cf, data, buf, len, err);
|
||||
|
||||
if(nread > 0) {
|
||||
DEBUGF(LOG_CF(data, cf, "[h2sid=%u] increase window by %zd",
|
||||
ctx->tunnel.stream_id, nread));
|
||||
CURL_TRC_CF(data, cf, "[%d] increase window by %zd",
|
||||
ctx->tunnel.stream_id, nread);
|
||||
nghttp2_session_consume(ctx->h2, ctx->tunnel.stream_id, (size_t)nread);
|
||||
}
|
||||
|
||||
result = proxy_h2_progress_egress(cf, data);
|
||||
if(result && result != CURLE_AGAIN) {
|
||||
if(result == CURLE_AGAIN) {
|
||||
/* pending data to send, need to be called again. Ideally, we'd
|
||||
* monitor the socket for POLLOUT, but we might not be in SENDING
|
||||
* transfer state any longer and are unable to make this happen.
|
||||
*/
|
||||
CURL_TRC_CF(data, cf, "[%d] egress blocked, DRAIN",
|
||||
ctx->tunnel.stream_id);
|
||||
drain_tunnel(cf, data, &ctx->tunnel);
|
||||
}
|
||||
else if(result) {
|
||||
*err = result;
|
||||
nread = -1;
|
||||
}
|
||||
@@ -1247,8 +1363,8 @@ out:
|
||||
* draining to avoid stalling when no socket events happen. */
|
||||
drain_tunnel(cf, data, &ctx->tunnel);
|
||||
}
|
||||
DEBUGF(LOG_CF(data, cf, "[h2sid=%u] cf_recv(len=%zu) -> %zd %d",
|
||||
ctx->tunnel.stream_id, len, nread, *err));
|
||||
CURL_TRC_CF(data, cf, "[%d] cf_recv(len=%zu) -> %zd %d",
|
||||
ctx->tunnel.stream_id, len, nread, *err);
|
||||
CF_DATA_RESTORE(cf, save);
|
||||
return nread;
|
||||
}
|
||||
@@ -1276,12 +1392,12 @@ static ssize_t cf_h2_proxy_send(struct Curl_cfilter *cf,
|
||||
goto out;
|
||||
}
|
||||
else if(ctx->tunnel.upload_blocked_len) {
|
||||
/* the data in `buf` has alread been submitted or added to the
|
||||
/* the data in `buf` has already been submitted or added to the
|
||||
* buffers, but have been EAGAINed on the last invocation. */
|
||||
DEBUGASSERT(len >= ctx->tunnel.upload_blocked_len);
|
||||
if(len < ctx->tunnel.upload_blocked_len) {
|
||||
/* Did we get called again with a smaller `len`? This should not
|
||||
* happend. We are not prepared to handle that. */
|
||||
* happen. We are not prepared to handle that. */
|
||||
failf(data, "HTTP/2 proxy, send again with decreased length");
|
||||
*err = CURLE_HTTP2;
|
||||
nwritten = -1;
|
||||
@@ -1289,6 +1405,7 @@ static ssize_t cf_h2_proxy_send(struct Curl_cfilter *cf,
|
||||
}
|
||||
nwritten = (ssize_t)ctx->tunnel.upload_blocked_len;
|
||||
ctx->tunnel.upload_blocked_len = 0;
|
||||
*err = CURLE_OK;
|
||||
}
|
||||
else {
|
||||
nwritten = Curl_bufq_write(&ctx->tunnel.sendbuf, buf, len, err);
|
||||
@@ -1309,6 +1426,13 @@ static ssize_t cf_h2_proxy_send(struct Curl_cfilter *cf,
|
||||
}
|
||||
}
|
||||
|
||||
result = proxy_h2_progress_ingress(cf, data);
|
||||
if(result) {
|
||||
*err = result;
|
||||
nwritten = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Call the nghttp2 send loop and flush to write ALL buffered data,
|
||||
* headers and/or request body completely out to the network */
|
||||
result = proxy_h2_progress_egress(cf, data);
|
||||
@@ -1339,24 +1463,25 @@ static ssize_t cf_h2_proxy_send(struct Curl_cfilter *cf,
|
||||
* proxy connection AND to UNHOLD all of them again when the
|
||||
* window increases.
|
||||
* We *could* iterate over all data on this conn maybe? */
|
||||
DEBUGF(LOG_CF(data, cf, "[h2sid=%d] remote flow "
|
||||
"window is exhausted", ctx->tunnel.stream_id));
|
||||
CURL_TRC_CF(data, cf, "[%d] remote flow "
|
||||
"window is exhausted", ctx->tunnel.stream_id);
|
||||
}
|
||||
|
||||
/* Whatever the cause, we need to return CURL_EAGAIN for this call.
|
||||
* We have unwritten state that needs us being invoked again and EAGAIN
|
||||
* is the only way to ensure that. */
|
||||
ctx->tunnel.upload_blocked_len = nwritten;
|
||||
DEBUGF(LOG_CF(data, cf, "[h2sid=%d] cf_send(len=%zu) BLOCK: win %u/%zu "
|
||||
"blocked_len=%zu",
|
||||
ctx->tunnel.stream_id, len,
|
||||
nghttp2_session_get_remote_window_size(ctx->h2), rwin,
|
||||
nwritten));
|
||||
CURL_TRC_CF(data, cf, "[%d] cf_send(len=%zu) BLOCK: win %u/%zu "
|
||||
"blocked_len=%zu",
|
||||
ctx->tunnel.stream_id, len,
|
||||
nghttp2_session_get_remote_window_size(ctx->h2), rwin,
|
||||
nwritten);
|
||||
drain_tunnel(cf, data, &ctx->tunnel);
|
||||
*err = CURLE_AGAIN;
|
||||
nwritten = -1;
|
||||
goto out;
|
||||
}
|
||||
else if(should_close_session(ctx)) {
|
||||
else if(proxy_h2_should_close_session(ctx)) {
|
||||
/* nghttp2 thinks this session is done. If the stream has not been
|
||||
* closed, this is an error state for out transfer */
|
||||
if(ctx->tunnel.closed) {
|
||||
@@ -1364,22 +1489,27 @@ static ssize_t cf_h2_proxy_send(struct Curl_cfilter *cf,
|
||||
nwritten = -1;
|
||||
}
|
||||
else {
|
||||
DEBUGF(LOG_CF(data, cf, "send: nothing to do in this session"));
|
||||
CURL_TRC_CF(data, cf, "[0] send: nothing to do in this session");
|
||||
*err = CURLE_HTTP2;
|
||||
nwritten = -1;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
DEBUGF(LOG_CF(data, cf, "[h2sid=%d] cf_send(len=%zu) -> %zd, %d, "
|
||||
"h2 windows %d-%d (stream-conn), "
|
||||
"buffers %zu-%zu (stream-conn)",
|
||||
ctx->tunnel.stream_id, len, nwritten, *err,
|
||||
nghttp2_session_get_stream_remote_window_size(
|
||||
if(!Curl_bufq_is_empty(&ctx->tunnel.recvbuf) &&
|
||||
(nwritten >= 0 || *err == CURLE_AGAIN)) {
|
||||
/* data pending and no fatal error to report. Need to trigger
|
||||
* draining to avoid stalling when no socket events happen. */
|
||||
drain_tunnel(cf, data, &ctx->tunnel);
|
||||
}
|
||||
CURL_TRC_CF(data, cf, "[%d] cf_send(len=%zu) -> %zd, %d, "
|
||||
"h2 windows %d-%d (stream-conn), buffers %zu-%zu (stream-conn)",
|
||||
ctx->tunnel.stream_id, len, nwritten, *err,
|
||||
nghttp2_session_get_stream_remote_window_size(
|
||||
ctx->h2, ctx->tunnel.stream_id),
|
||||
nghttp2_session_get_remote_window_size(ctx->h2),
|
||||
Curl_bufq_len(&ctx->tunnel.sendbuf),
|
||||
Curl_bufq_len(&ctx->outbufq)));
|
||||
nghttp2_session_get_remote_window_size(ctx->h2),
|
||||
Curl_bufq_len(&ctx->tunnel.sendbuf),
|
||||
Curl_bufq_len(&ctx->outbufq));
|
||||
CF_DATA_RESTORE(cf, save);
|
||||
return nwritten;
|
||||
}
|
||||
@@ -1409,7 +1539,7 @@ static bool proxy_h2_connisalive(struct Curl_cfilter *cf,
|
||||
/* immediate error, considered dead */
|
||||
alive = FALSE;
|
||||
else {
|
||||
alive = !should_close_session(ctx);
|
||||
alive = !proxy_h2_should_close_session(ctx);
|
||||
}
|
||||
}
|
||||
else if(result != CURLE_AGAIN) {
|
||||
@@ -1431,8 +1561,8 @@ static bool cf_h2_proxy_is_alive(struct Curl_cfilter *cf,
|
||||
|
||||
CF_DATA_SAVE(save, cf, data);
|
||||
result = (ctx && ctx->h2 && proxy_h2_connisalive(cf, data, input_pending));
|
||||
DEBUGF(LOG_CF(data, cf, "conn alive -> %d, input_pending=%d",
|
||||
result, *input_pending));
|
||||
CURL_TRC_CF(data, cf, "[0] conn alive -> %d, input_pending=%d",
|
||||
result, *input_pending);
|
||||
CF_DATA_RESTORE(cf, save);
|
||||
return result;
|
||||
}
|
||||
@@ -1440,7 +1570,7 @@ static bool cf_h2_proxy_is_alive(struct Curl_cfilter *cf,
|
||||
struct Curl_cftype Curl_cft_h2_proxy = {
|
||||
"H2-PROXY",
|
||||
CF_TYPE_IP_CONNECT,
|
||||
CURL_LOG_DEFAULT,
|
||||
CURL_LOG_LVL_NONE,
|
||||
cf_h2_proxy_destroy,
|
||||
cf_h2_proxy_connect,
|
||||
cf_h2_proxy_close,
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#include "urldata.h"
|
||||
#include "cfilters.h"
|
||||
#include "cf-haproxy.h"
|
||||
#include "curl_log.h"
|
||||
#include "curl_trc.h"
|
||||
#include "multiif.h"
|
||||
|
||||
/* The last 3 #include files should be in this order */
|
||||
@@ -86,12 +86,12 @@ static CURLcode cf_haproxy_date_out_set(struct Curl_cfilter*cf,
|
||||
if(data->set.str[STRING_HAPROXY_CLIENT_IP])
|
||||
client_ip = data->set.str[STRING_HAPROXY_CLIENT_IP];
|
||||
else
|
||||
client_ip = data->info.conn_primary_ip;
|
||||
client_ip = data->info.conn_local_ip;
|
||||
|
||||
result = Curl_dyn_addf(&ctx->data_out, "PROXY %s %s %s %i %i\r\n",
|
||||
tcp_version,
|
||||
data->info.conn_local_ip,
|
||||
client_ip,
|
||||
data->info.conn_primary_ip,
|
||||
data->info.conn_local_port,
|
||||
data->info.conn_primary_port);
|
||||
|
||||
@@ -157,14 +157,14 @@ static void cf_haproxy_destroy(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
(void)data;
|
||||
DEBUGF(LOG_CF(data, cf, "destroy"));
|
||||
CURL_TRC_CF(data, cf, "destroy");
|
||||
cf_haproxy_ctx_free(cf->ctx);
|
||||
}
|
||||
|
||||
static void cf_haproxy_close(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
DEBUGF(LOG_CF(data, cf, "close"));
|
||||
CURL_TRC_CF(data, cf, "close");
|
||||
cf->connected = FALSE;
|
||||
cf_haproxy_ctx_reset(cf->ctx);
|
||||
if(cf->next)
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
#include "urldata.h"
|
||||
#include <curl/curl.h>
|
||||
#include "curl_log.h"
|
||||
#include "curl_trc.h"
|
||||
#include "cfilters.h"
|
||||
#include "connect.h"
|
||||
#include "multiif.h"
|
||||
@@ -165,9 +165,9 @@ static CURLcode baller_connected(struct Curl_cfilter *cf,
|
||||
if(winner != &ctx->h21_baller)
|
||||
cf_hc_baller_reset(&ctx->h21_baller, data);
|
||||
|
||||
DEBUGF(LOG_CF(data, cf, "connect+handshake %s: %dms, 1st data: %dms",
|
||||
winner->name, (int)Curl_timediff(Curl_now(), winner->started),
|
||||
cf_hc_baller_reply_ms(winner, data)));
|
||||
CURL_TRC_CF(data, cf, "connect+handshake %s: %dms, 1st data: %dms",
|
||||
winner->name, (int)Curl_timediff(Curl_now(), winner->started),
|
||||
cf_hc_baller_reply_ms(winner, data));
|
||||
cf->next = winner->cf;
|
||||
winner->cf = NULL;
|
||||
|
||||
@@ -218,16 +218,16 @@ static bool time_to_start_h21(struct Curl_cfilter *cf,
|
||||
|
||||
elapsed_ms = Curl_timediff(now, ctx->started);
|
||||
if(elapsed_ms >= ctx->hard_eyeballs_timeout_ms) {
|
||||
DEBUGF(LOG_CF(data, cf, "hard timeout of %dms reached, starting h21",
|
||||
ctx->hard_eyeballs_timeout_ms));
|
||||
CURL_TRC_CF(data, cf, "hard timeout of %dms reached, starting h21",
|
||||
ctx->hard_eyeballs_timeout_ms);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if(elapsed_ms >= ctx->soft_eyeballs_timeout_ms) {
|
||||
if(cf_hc_baller_reply_ms(&ctx->h3_baller, data) < 0) {
|
||||
DEBUGF(LOG_CF(data, cf, "soft timeout of %dms reached, h3 has not "
|
||||
"seen any data, starting h21",
|
||||
ctx->soft_eyeballs_timeout_ms));
|
||||
CURL_TRC_CF(data, cf, "soft timeout of %dms reached, h3 has not "
|
||||
"seen any data, starting h21",
|
||||
ctx->soft_eyeballs_timeout_ms);
|
||||
return TRUE;
|
||||
}
|
||||
/* set the effective hard timeout again */
|
||||
@@ -258,7 +258,7 @@ static CURLcode cf_hc_connect(struct Curl_cfilter *cf,
|
||||
DEBUGASSERT(!ctx->h3_baller.cf);
|
||||
DEBUGASSERT(!ctx->h21_baller.cf);
|
||||
DEBUGASSERT(!cf->next);
|
||||
DEBUGF(LOG_CF(data, cf, "connect, init"));
|
||||
CURL_TRC_CF(data, cf, "connect, init");
|
||||
ctx->started = now;
|
||||
if(ctx->h3_baller.enabled) {
|
||||
cf_hc_baller_init(&ctx->h3_baller, cf, data, "h3", TRNSPRT_QUIC);
|
||||
@@ -286,7 +286,7 @@ static CURLcode cf_hc_connect(struct Curl_cfilter *cf,
|
||||
}
|
||||
|
||||
if(cf_hc_baller_is_active(&ctx->h21_baller)) {
|
||||
DEBUGF(LOG_CF(data, cf, "connect, check h21"));
|
||||
CURL_TRC_CF(data, cf, "connect, check h21");
|
||||
result = cf_hc_baller_connect(&ctx->h21_baller, cf, data, done);
|
||||
if(!result && *done) {
|
||||
result = baller_connected(cf, data, &ctx->h21_baller);
|
||||
@@ -297,7 +297,7 @@ static CURLcode cf_hc_connect(struct Curl_cfilter *cf,
|
||||
if((!ctx->h3_baller.enabled || ctx->h3_baller.result) &&
|
||||
(!ctx->h21_baller.enabled || ctx->h21_baller.result)) {
|
||||
/* both failed or disabled. we give up */
|
||||
DEBUGF(LOG_CF(data, cf, "connect, all failed"));
|
||||
CURL_TRC_CF(data, cf, "connect, all failed");
|
||||
result = ctx->result = ctx->h3_baller.enabled?
|
||||
ctx->h3_baller.result : ctx->h21_baller.result;
|
||||
ctx->state = CF_HC_FAILURE;
|
||||
@@ -321,7 +321,7 @@ static CURLcode cf_hc_connect(struct Curl_cfilter *cf,
|
||||
}
|
||||
|
||||
out:
|
||||
DEBUGF(LOG_CF(data, cf, "connect -> %d, done=%d", result, *done));
|
||||
CURL_TRC_CF(data, cf, "connect -> %d, done=%d", result, *done);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -345,7 +345,7 @@ static int cf_hc_get_select_socks(struct Curl_cfilter *cf,
|
||||
if(!cf_hc_baller_is_active(b))
|
||||
continue;
|
||||
brc = Curl_conn_cf_get_select_socks(b->cf, data, bsocks);
|
||||
DEBUGF(LOG_CF(data, cf, "get_selected_socks(%s) -> %x", b->name, brc));
|
||||
CURL_TRC_CF(data, cf, "get_selected_socks(%s) -> %x", b->name, brc);
|
||||
if(!brc)
|
||||
continue;
|
||||
for(j = 0; j < MAX_SOCKSPEREASYHANDLE && s < MAX_SOCKSPEREASYHANDLE; ++j) {
|
||||
@@ -359,7 +359,7 @@ static int cf_hc_get_select_socks(struct Curl_cfilter *cf,
|
||||
}
|
||||
}
|
||||
}
|
||||
DEBUGF(LOG_CF(data, cf, "get_selected_socks -> %x", rc));
|
||||
CURL_TRC_CF(data, cf, "get_selected_socks -> %x", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -371,7 +371,7 @@ static bool cf_hc_data_pending(struct Curl_cfilter *cf,
|
||||
if(cf->connected)
|
||||
return cf->next->cft->has_data_pending(cf->next, data);
|
||||
|
||||
DEBUGF(LOG_CF((struct Curl_easy *)data, cf, "data_pending"));
|
||||
CURL_TRC_CF((struct Curl_easy *)data, cf, "data_pending");
|
||||
return cf_hc_baller_data_pending(&ctx->h3_baller, data)
|
||||
|| cf_hc_baller_data_pending(&ctx->h21_baller, data);
|
||||
}
|
||||
@@ -427,7 +427,7 @@ static CURLcode cf_hc_query(struct Curl_cfilter *cf,
|
||||
|
||||
static void cf_hc_close(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
{
|
||||
DEBUGF(LOG_CF(data, cf, "close"));
|
||||
CURL_TRC_CF(data, cf, "close");
|
||||
cf_hc_reset(cf, data);
|
||||
cf->connected = FALSE;
|
||||
|
||||
@@ -442,7 +442,7 @@ static void cf_hc_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
struct cf_hc_ctx *ctx = cf->ctx;
|
||||
|
||||
(void)data;
|
||||
DEBUGF(LOG_CF(data, cf, "destroy"));
|
||||
CURL_TRC_CF(data, cf, "destroy");
|
||||
cf_hc_reset(cf, data);
|
||||
Curl_safefree(ctx);
|
||||
}
|
||||
@@ -450,7 +450,7 @@ static void cf_hc_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
struct Curl_cftype Curl_cft_http_connect = {
|
||||
"HTTPS-CONNECT",
|
||||
0,
|
||||
CURL_LOG_DEFAULT,
|
||||
CURL_LOG_LVL_NONE,
|
||||
cf_hc_destroy,
|
||||
cf_hc_connect,
|
||||
cf_hc_close,
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
#include "warnless.h"
|
||||
#include "conncache.h"
|
||||
#include "multihandle.h"
|
||||
#include "rand.h"
|
||||
#include "share.h"
|
||||
#include "version_win32.h"
|
||||
|
||||
@@ -390,6 +391,7 @@ void Curl_sndbufset(curl_socket_t sockfd)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef CURL_DISABLE_BINDLOCAL
|
||||
static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn,
|
||||
curl_socket_t sockfd, int af, unsigned int scope)
|
||||
{
|
||||
@@ -444,29 +446,24 @@ static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn,
|
||||
/* interface */
|
||||
if(!is_host) {
|
||||
#ifdef SO_BINDTODEVICE
|
||||
/* I am not sure any other OSs than Linux that provide this feature,
|
||||
* and at the least I cannot test. --Ben
|
||||
/*
|
||||
* This binds the local socket to a particular interface. This will
|
||||
* force even requests to other local interfaces to go out the external
|
||||
* interface. Only bind to the interface when specified as interface,
|
||||
* not just as a hostname or ip address.
|
||||
*
|
||||
* This feature allows one to tightly bind the local socket to a
|
||||
* particular interface. This will force even requests to other
|
||||
* local interfaces to go out the external interface.
|
||||
*
|
||||
*
|
||||
* Only bind to the interface when specified as interface, not just
|
||||
* as a hostname or ip address.
|
||||
*
|
||||
* interface might be a VRF, eg: vrf-blue, which means it cannot be
|
||||
* converted to an IP address and would fail Curl_if2ip. Simply try
|
||||
* to use it straight away.
|
||||
* The interface might be a VRF, eg: vrf-blue, which means it cannot be
|
||||
* converted to an IP address and would fail Curl_if2ip. Simply try to
|
||||
* use it straight away.
|
||||
*/
|
||||
if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
|
||||
dev, (curl_socklen_t)strlen(dev) + 1) == 0) {
|
||||
/* This is typically "errno 1, error: Operation not permitted" if
|
||||
* you're not running as root or another suitable privileged
|
||||
* user.
|
||||
* If it succeeds it means the parameter was a valid interface and
|
||||
* not an IP address. Return immediately.
|
||||
/* This is often "errno 1, error: Operation not permitted" if you're
|
||||
* not running as root or another suitable privileged user. If it
|
||||
* succeeds it means the parameter was a valid interface and not an IP
|
||||
* address. Return immediately.
|
||||
*/
|
||||
infof(data, "socket successfully bound to interface '%s'", dev);
|
||||
return CURLE_OK;
|
||||
}
|
||||
#endif
|
||||
@@ -632,8 +629,8 @@ static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn,
|
||||
port++; /* try next port */
|
||||
if(port == 0)
|
||||
break;
|
||||
infof(data, "Bind to local port %hu failed, trying next", port - 1);
|
||||
/* We re-use/clobber the port variable here below */
|
||||
infof(data, "Bind to local port %d failed, trying next", port - 1);
|
||||
/* We reuse/clobber the port variable here below */
|
||||
if(sock->sa_family == AF_INET)
|
||||
si4->sin_port = ntohs(port);
|
||||
#ifdef ENABLE_IPV6
|
||||
@@ -653,6 +650,7 @@ static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn,
|
||||
|
||||
return CURLE_INTERFACE_FAILED;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* verifyconnect() returns TRUE if the connect really has happened.
|
||||
@@ -727,8 +725,6 @@ static bool verifyconnect(curl_socket_t sockfd, int *error)
|
||||
static CURLcode socket_connect_result(struct Curl_easy *data,
|
||||
const char *ipaddress, int error)
|
||||
{
|
||||
char buffer[STRERROR_LEN];
|
||||
|
||||
switch(error) {
|
||||
case EINPROGRESS:
|
||||
case EWOULDBLOCK:
|
||||
@@ -745,8 +741,15 @@ static CURLcode socket_connect_result(struct Curl_easy *data,
|
||||
|
||||
default:
|
||||
/* unknown error, fallthrough and try another address! */
|
||||
infof(data, "Immediate connect fail for %s: %s",
|
||||
ipaddress, Curl_strerror(error, buffer, sizeof(buffer)));
|
||||
#ifdef CURL_DISABLE_VERBOSE_STRINGS
|
||||
(void)ipaddress;
|
||||
#else
|
||||
{
|
||||
char buffer[STRERROR_LEN];
|
||||
infof(data, "Immediate connect fail for %s: %s",
|
||||
ipaddress, Curl_strerror(error, buffer, sizeof(buffer)));
|
||||
}
|
||||
#endif
|
||||
data->state.os_errno = error;
|
||||
/* connect failed */
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
@@ -775,6 +778,10 @@ struct cf_socket_ctx {
|
||||
struct curltime connected_at; /* when socket connected/got first byte */
|
||||
struct curltime first_byte_at; /* when first byte was recvd */
|
||||
int error; /* errno of last failure or 0 */
|
||||
#ifdef DEBUGBUILD
|
||||
int wblock_percent; /* percent of writes doing EAGAIN */
|
||||
int wpartial_percent; /* percent of bytes written in send */
|
||||
#endif
|
||||
BIT(got_first_byte); /* if first byte was received */
|
||||
BIT(accepted); /* socket was accepted, not connected */
|
||||
BIT(active);
|
||||
@@ -790,6 +797,22 @@ static void cf_socket_ctx_init(struct cf_socket_ctx *ctx,
|
||||
ctx->transport = transport;
|
||||
Curl_sock_assign_addr(&ctx->addr, ai, transport);
|
||||
Curl_bufq_init(&ctx->recvbuf, NW_RECV_CHUNK_SIZE, NW_RECV_CHUNKS);
|
||||
#ifdef DEBUGBUILD
|
||||
{
|
||||
char *p = getenv("CURL_DBG_SOCK_WBLOCK");
|
||||
if(p) {
|
||||
long l = strtol(p, NULL, 10);
|
||||
if(l >= 0 && l <= 100)
|
||||
ctx->wblock_percent = (int)l;
|
||||
}
|
||||
p = getenv("CURL_DBG_SOCK_WPARTIAL");
|
||||
if(p) {
|
||||
long l = strtol(p, NULL, 10);
|
||||
if(l >= 0 && l <= 100)
|
||||
ctx->wpartial_percent = (int)l;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
struct reader_ctx {
|
||||
@@ -836,8 +859,8 @@ static ssize_t nw_in_read(void *reader_ctx,
|
||||
nread = -1;
|
||||
}
|
||||
}
|
||||
DEBUGF(LOG_CF(rctx->data, rctx->cf, "nw_in_read(len=%zu) -> %d, err=%d",
|
||||
len, (int)nread, *err));
|
||||
CURL_TRC_CF(rctx->data, rctx->cf, "nw_in_read(len=%zu) -> %d, err=%d",
|
||||
len, (int)nread, *err);
|
||||
return nread;
|
||||
}
|
||||
|
||||
@@ -852,14 +875,14 @@ static void cf_socket_close(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
* closed it) and we just forget about it.
|
||||
*/
|
||||
if(ctx->sock == cf->conn->sock[cf->sockindex]) {
|
||||
DEBUGF(LOG_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
|
||||
", active)", ctx->sock));
|
||||
CURL_TRC_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
|
||||
", active)", ctx->sock);
|
||||
socket_close(data, cf->conn, !ctx->accepted, ctx->sock);
|
||||
cf->conn->sock[cf->sockindex] = CURL_SOCKET_BAD;
|
||||
}
|
||||
else {
|
||||
DEBUGF(LOG_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
|
||||
") no longer at conn->sock[], discarding", ctx->sock));
|
||||
CURL_TRC_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
|
||||
") no longer at conn->sock[], discarding", ctx->sock);
|
||||
/* TODO: we do not want this to happen. Need to check which
|
||||
* code is messing with conn->sock[cf->sockindex] */
|
||||
}
|
||||
@@ -869,8 +892,8 @@ static void cf_socket_close(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
}
|
||||
else {
|
||||
/* this is our local socket, we did never publish it */
|
||||
DEBUGF(LOG_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
|
||||
", not active)", ctx->sock));
|
||||
CURL_TRC_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
|
||||
", not active)", ctx->sock);
|
||||
socket_close(data, cf->conn, !ctx->accepted, ctx->sock);
|
||||
ctx->sock = CURL_SOCKET_BAD;
|
||||
}
|
||||
@@ -889,7 +912,7 @@ static void cf_socket_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
struct cf_socket_ctx *ctx = cf->ctx;
|
||||
|
||||
cf_socket_close(cf, data);
|
||||
DEBUGF(LOG_CF(data, cf, "destroy"));
|
||||
CURL_TRC_CF(data, cf, "destroy");
|
||||
Curl_bufq_free(&ctx->recvbuf);
|
||||
free(ctx);
|
||||
cf->ctx = NULL;
|
||||
@@ -957,7 +980,6 @@ static CURLcode cf_socket_open(struct Curl_cfilter *cf,
|
||||
bool isconnected = FALSE;
|
||||
CURLcode result = CURLE_COULDNT_CONNECT;
|
||||
bool is_tcp;
|
||||
const char *ipmsg;
|
||||
|
||||
(void)data;
|
||||
DEBUGASSERT(ctx->sock == CURL_SOCKET_BAD);
|
||||
@@ -970,15 +992,20 @@ static CURLcode cf_socket_open(struct Curl_cfilter *cf,
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
#ifndef CURL_DISABLE_VERBOSE_STRINGS
|
||||
{
|
||||
const char *ipmsg;
|
||||
#ifdef ENABLE_IPV6
|
||||
if(ctx->addr.family == AF_INET6) {
|
||||
set_ipv6_v6only(ctx->sock, 0);
|
||||
ipmsg = " Trying [%s]:%d...";
|
||||
}
|
||||
else
|
||||
if(ctx->addr.family == AF_INET6) {
|
||||
set_ipv6_v6only(ctx->sock, 0);
|
||||
ipmsg = " Trying [%s]:%d...";
|
||||
}
|
||||
else
|
||||
#endif
|
||||
ipmsg = " Trying %s:%d...";
|
||||
infof(data, ipmsg, ctx->r_ip, ctx->r_port);
|
||||
}
|
||||
#endif
|
||||
ipmsg = " Trying %s:%d...";
|
||||
infof(data, ipmsg, ctx->r_ip, ctx->r_port);
|
||||
|
||||
#ifdef ENABLE_IPV6
|
||||
is_tcp = (ctx->addr.family == AF_INET
|
||||
@@ -1014,6 +1041,7 @@ static CURLcode cf_socket_open(struct Curl_cfilter *cf,
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CURL_DISABLE_BINDLOCAL
|
||||
/* possibly bind the local end to an IP, interface or port */
|
||||
if(ctx->addr.family == AF_INET
|
||||
#ifdef ENABLE_IPV6
|
||||
@@ -1031,6 +1059,7 @@ static CURLcode cf_socket_open(struct Curl_cfilter *cf,
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* set socket non-blocking */
|
||||
(void)curlx_nonblock(ctx->sock, TRUE);
|
||||
@@ -1047,8 +1076,8 @@ out:
|
||||
ctx->connected_at = Curl_now();
|
||||
cf->connected = TRUE;
|
||||
}
|
||||
DEBUGF(LOG_CF(data, cf, "cf_socket_open() -> %d, fd=%" CURL_FORMAT_SOCKET_T,
|
||||
result, ctx->sock));
|
||||
CURL_TRC_CF(data, cf, "cf_socket_open() -> %d, fd=%" CURL_FORMAT_SOCKET_T,
|
||||
result, ctx->sock);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1155,7 +1184,7 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf,
|
||||
rc = SOCKET_WRITABLE(ctx->sock, 0);
|
||||
|
||||
if(rc == 0) { /* no connection yet */
|
||||
DEBUGF(LOG_CF(data, cf, "not connected yet"));
|
||||
CURL_TRC_CF(data, cf, "not connected yet");
|
||||
return CURLE_OK;
|
||||
}
|
||||
else if(rc == CURL_CSELECT_OUT || cf->conn->bits.tcp_fastopen) {
|
||||
@@ -1165,7 +1194,7 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf,
|
||||
set_local_ip(cf, data);
|
||||
*done = TRUE;
|
||||
cf->connected = TRUE;
|
||||
DEBUGF(LOG_CF(data, cf, "connected"));
|
||||
CURL_TRC_CF(data, cf, "connected");
|
||||
return CURLE_OK;
|
||||
}
|
||||
}
|
||||
@@ -1245,11 +1274,34 @@ static ssize_t cf_socket_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
struct cf_socket_ctx *ctx = cf->ctx;
|
||||
curl_socket_t fdsave;
|
||||
ssize_t nwritten;
|
||||
size_t orig_len = len;
|
||||
|
||||
*err = CURLE_OK;
|
||||
fdsave = cf->conn->sock[cf->sockindex];
|
||||
cf->conn->sock[cf->sockindex] = ctx->sock;
|
||||
|
||||
#ifdef DEBUGBUILD
|
||||
/* simulate network blocking/partial writes */
|
||||
if(ctx->wblock_percent > 0) {
|
||||
unsigned char c;
|
||||
Curl_rand(data, &c, 1);
|
||||
if(c >= ((100-ctx->wblock_percent)*256/100)) {
|
||||
CURL_TRC_CF(data, cf, "send(len=%zu) SIMULATE EWOULDBLOCK", orig_len);
|
||||
*err = CURLE_AGAIN;
|
||||
nwritten = -1;
|
||||
cf->conn->sock[cf->sockindex] = fdsave;
|
||||
return nwritten;
|
||||
}
|
||||
}
|
||||
if(cf->cft != &Curl_cft_udp && ctx->wpartial_percent > 0 && len > 8) {
|
||||
len = len * ctx->wpartial_percent / 100;
|
||||
if(!len)
|
||||
len = 1;
|
||||
CURL_TRC_CF(data, cf, "send(len=%zu) SIMULATE partial write of %zu bytes",
|
||||
orig_len, len);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MSG_FASTOPEN) && !defined(TCP_FASTOPEN_CONNECT) /* Linux */
|
||||
if(cf->conn->bits.tcp_fastopen) {
|
||||
nwritten = sendto(ctx->sock, buf, len, MSG_FASTOPEN,
|
||||
@@ -1288,8 +1340,8 @@ static ssize_t cf_socket_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
}
|
||||
}
|
||||
|
||||
DEBUGF(LOG_CF(data, cf, "send(len=%zu) -> %d, err=%d",
|
||||
len, (int)nwritten, *err));
|
||||
CURL_TRC_CF(data, cf, "send(len=%zu) -> %d, err=%d",
|
||||
orig_len, (int)nwritten, *err);
|
||||
cf->conn->sock[cf->sockindex] = fdsave;
|
||||
return nwritten;
|
||||
}
|
||||
@@ -1307,7 +1359,7 @@ static ssize_t cf_socket_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
cf->conn->sock[cf->sockindex] = ctx->sock;
|
||||
|
||||
if(ctx->buffer_recv && !Curl_bufq_is_empty(&ctx->recvbuf)) {
|
||||
DEBUGF(LOG_CF(data, cf, "recv from buffer"));
|
||||
CURL_TRC_CF(data, cf, "recv from buffer");
|
||||
nread = Curl_bufq_read(&ctx->recvbuf, (unsigned char *)buf, len, err);
|
||||
}
|
||||
else {
|
||||
@@ -1324,7 +1376,7 @@ static ssize_t cf_socket_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
if(nwritten < 0 && !Curl_bufq_is_empty(&ctx->recvbuf)) {
|
||||
/* we have a partial read with an error. need to deliver
|
||||
* what we got, return the error later. */
|
||||
DEBUGF(LOG_CF(data, cf, "partial read: empty buffer first"));
|
||||
CURL_TRC_CF(data, cf, "partial read: empty buffer first");
|
||||
nread = Curl_bufq_read(&ctx->recvbuf, (unsigned char *)buf, len, err);
|
||||
}
|
||||
else if(nwritten < 0) {
|
||||
@@ -1337,7 +1389,7 @@ static ssize_t cf_socket_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
nread = 0;
|
||||
}
|
||||
else {
|
||||
DEBUGF(LOG_CF(data, cf, "buffered %zd additional bytes", nwritten));
|
||||
CURL_TRC_CF(data, cf, "buffered %zd additional bytes", nwritten);
|
||||
nread = Curl_bufq_read(&ctx->recvbuf, (unsigned char *)buf, len, err);
|
||||
}
|
||||
}
|
||||
@@ -1347,8 +1399,8 @@ static ssize_t cf_socket_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
}
|
||||
|
||||
out:
|
||||
DEBUGF(LOG_CF(data, cf, "recv(len=%zu) -> %d, err=%d", len, (int)nread,
|
||||
*err));
|
||||
CURL_TRC_CF(data, cf, "recv(len=%zu) -> %d, err=%d", len, (int)nread,
|
||||
*err);
|
||||
if(nread > 0 && !ctx->got_first_byte) {
|
||||
ctx->first_byte_at = Curl_now();
|
||||
ctx->got_first_byte = TRUE;
|
||||
@@ -1455,19 +1507,19 @@ static bool cf_socket_conn_is_alive(struct Curl_cfilter *cf,
|
||||
|
||||
r = Curl_poll(pfd, 1, 0);
|
||||
if(r < 0) {
|
||||
DEBUGF(LOG_CF(data, cf, "is_alive: poll error, assume dead"));
|
||||
CURL_TRC_CF(data, cf, "is_alive: poll error, assume dead");
|
||||
return FALSE;
|
||||
}
|
||||
else if(r == 0) {
|
||||
DEBUGF(LOG_CF(data, cf, "is_alive: poll timeout, assume alive"));
|
||||
CURL_TRC_CF(data, cf, "is_alive: poll timeout, assume alive");
|
||||
return TRUE;
|
||||
}
|
||||
else if(pfd[0].revents & (POLLERR|POLLHUP|POLLPRI|POLLNVAL)) {
|
||||
DEBUGF(LOG_CF(data, cf, "is_alive: err/hup/etc events, assume dead"));
|
||||
CURL_TRC_CF(data, cf, "is_alive: err/hup/etc events, assume dead");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DEBUGF(LOG_CF(data, cf, "is_alive: valid events, looks alive"));
|
||||
CURL_TRC_CF(data, cf, "is_alive: valid events, looks alive");
|
||||
*input_pending = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
@@ -1520,7 +1572,7 @@ static CURLcode cf_socket_query(struct Curl_cfilter *cf,
|
||||
struct Curl_cftype Curl_cft_tcp = {
|
||||
"TCP",
|
||||
CF_TYPE_IP_CONNECT,
|
||||
CURL_LOG_DEFAULT,
|
||||
CURL_LOG_LVL_NONE,
|
||||
cf_socket_destroy,
|
||||
cf_tcp_connect,
|
||||
cf_socket_close,
|
||||
@@ -1581,10 +1633,10 @@ static CURLcode cf_udp_setup_quic(struct Curl_cfilter *cf,
|
||||
return socket_connect_result(data, ctx->r_ip, SOCKERRNO);
|
||||
}
|
||||
set_local_ip(cf, data);
|
||||
DEBUGF(LOG_CF(data, cf, "%s socket %" CURL_FORMAT_SOCKET_T
|
||||
" connected: [%s:%d] -> [%s:%d]",
|
||||
(ctx->transport == TRNSPRT_QUIC)? "QUIC" : "UDP",
|
||||
ctx->sock, ctx->l_ip, ctx->l_port, ctx->r_ip, ctx->r_port));
|
||||
CURL_TRC_CF(data, cf, "%s socket %" CURL_FORMAT_SOCKET_T
|
||||
" connected: [%s:%d] -> [%s:%d]",
|
||||
(ctx->transport == TRNSPRT_QUIC)? "QUIC" : "UDP",
|
||||
ctx->sock, ctx->l_ip, ctx->l_port, ctx->r_ip, ctx->r_port);
|
||||
|
||||
(void)curlx_nonblock(ctx->sock, TRUE);
|
||||
switch(ctx->addr.family) {
|
||||
@@ -1624,7 +1676,7 @@ static CURLcode cf_udp_connect(struct Curl_cfilter *cf,
|
||||
if(ctx->sock == CURL_SOCKET_BAD) {
|
||||
result = cf_socket_open(cf, data);
|
||||
if(result) {
|
||||
DEBUGF(LOG_CF(data, cf, "cf_udp_connect(), open failed -> %d", result));
|
||||
CURL_TRC_CF(data, cf, "cf_udp_connect(), open failed -> %d", result);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1632,13 +1684,13 @@ static CURLcode cf_udp_connect(struct Curl_cfilter *cf,
|
||||
result = cf_udp_setup_quic(cf, data);
|
||||
if(result)
|
||||
goto out;
|
||||
DEBUGF(LOG_CF(data, cf, "cf_udp_connect(), opened socket=%"
|
||||
CURL_FORMAT_SOCKET_T " (%s:%d)",
|
||||
ctx->sock, ctx->l_ip, ctx->l_port));
|
||||
CURL_TRC_CF(data, cf, "cf_udp_connect(), opened socket=%"
|
||||
CURL_FORMAT_SOCKET_T " (%s:%d)",
|
||||
ctx->sock, ctx->l_ip, ctx->l_port);
|
||||
}
|
||||
else {
|
||||
DEBUGF(LOG_CF(data, cf, "cf_udp_connect(), opened socket=%"
|
||||
CURL_FORMAT_SOCKET_T " (unconnected)", ctx->sock));
|
||||
CURL_TRC_CF(data, cf, "cf_udp_connect(), opened socket=%"
|
||||
CURL_FORMAT_SOCKET_T " (unconnected)", ctx->sock);
|
||||
}
|
||||
*done = TRUE;
|
||||
cf->connected = TRUE;
|
||||
@@ -1650,7 +1702,7 @@ out:
|
||||
struct Curl_cftype Curl_cft_udp = {
|
||||
"UDP",
|
||||
CF_TYPE_IP_CONNECT,
|
||||
CURL_LOG_DEFAULT,
|
||||
CURL_LOG_LVL_NONE,
|
||||
cf_socket_destroy,
|
||||
cf_udp_connect,
|
||||
cf_socket_close,
|
||||
@@ -1701,7 +1753,7 @@ out:
|
||||
struct Curl_cftype Curl_cft_unix = {
|
||||
"UNIX",
|
||||
CF_TYPE_IP_CONNECT,
|
||||
CURL_LOG_DEFAULT,
|
||||
CURL_LOG_LVL_NONE,
|
||||
cf_socket_destroy,
|
||||
cf_tcp_connect,
|
||||
cf_socket_close,
|
||||
@@ -1765,7 +1817,7 @@ static CURLcode cf_tcp_accept_connect(struct Curl_cfilter *cf,
|
||||
struct Curl_cftype Curl_cft_tcp_accept = {
|
||||
"TCP-ACCEPT",
|
||||
CF_TYPE_IP_CONNECT,
|
||||
CURL_LOG_DEFAULT,
|
||||
CURL_LOG_LVL_NONE,
|
||||
cf_socket_destroy,
|
||||
cf_tcp_accept_connect,
|
||||
cf_socket_close,
|
||||
@@ -1810,8 +1862,8 @@ CURLcode Curl_conn_tcp_listen_set(struct Curl_easy *data,
|
||||
ctx->active = TRUE;
|
||||
ctx->connected_at = Curl_now();
|
||||
cf->connected = TRUE;
|
||||
DEBUGF(LOG_CF(data, cf, "Curl_conn_tcp_listen_set(%"
|
||||
CURL_FORMAT_SOCKET_T ")", ctx->sock));
|
||||
CURL_TRC_CF(data, cf, "Curl_conn_tcp_listen_set(%"
|
||||
CURL_FORMAT_SOCKET_T ")", ctx->sock);
|
||||
|
||||
out:
|
||||
if(result) {
|
||||
@@ -1875,9 +1927,9 @@ CURLcode Curl_conn_tcp_accepted_set(struct Curl_easy *data,
|
||||
ctx->accepted = TRUE;
|
||||
ctx->connected_at = Curl_now();
|
||||
cf->connected = TRUE;
|
||||
DEBUGF(LOG_CF(data, cf, "accepted_set(sock=%" CURL_FORMAT_SOCKET_T
|
||||
", remote=%s port=%d)",
|
||||
ctx->sock, ctx->r_ip, ctx->r_port));
|
||||
CURL_TRC_CF(data, cf, "accepted_set(sock=%" CURL_FORMAT_SOCKET_T
|
||||
", remote=%s port=%d)",
|
||||
ctx->sock, ctx->r_ip, ctx->r_port);
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
@@ -1922,4 +1974,3 @@ CURLcode Curl_cf_socket_peek(struct Curl_cfilter *cf,
|
||||
}
|
||||
return CURLE_FAILED_INIT;
|
||||
}
|
||||
|
||||
|
||||
@@ -238,7 +238,7 @@ void Curl_conn_cf_add(struct Curl_easy *data,
|
||||
cf->conn = conn;
|
||||
cf->sockindex = index;
|
||||
conn->cfilter[index] = cf;
|
||||
DEBUGF(LOG_CF(data, cf, "added"));
|
||||
CURL_TRC_CF(data, cf, "added");
|
||||
}
|
||||
|
||||
void Curl_conn_cf_insert_after(struct Curl_cfilter *cf_at,
|
||||
@@ -646,4 +646,3 @@ size_t Curl_conn_get_max_concurrent(struct Curl_easy *data,
|
||||
&n, NULL) : CURLE_UNKNOWN_OPTION;
|
||||
return (result || n <= 0)? 1 : (size_t)n;
|
||||
}
|
||||
|
||||
|
||||
@@ -381,6 +381,11 @@ struct cf_he_ctx {
|
||||
struct curltime started;
|
||||
};
|
||||
|
||||
/* when there are more than one IP address left to use, this macro returns how
|
||||
much of the given timeout to spend on *this* attempt */
|
||||
#define TIMEOUT_LARGE 600
|
||||
#define USETIME(ms) ((ms > TIMEOUT_LARGE) ? (ms / 2) : ms)
|
||||
|
||||
static CURLcode eyeballer_new(struct eyeballer **pballer,
|
||||
cf_ip_connect_create *cf_create,
|
||||
const struct Curl_addrinfo *addr,
|
||||
@@ -408,7 +413,7 @@ static CURLcode eyeballer_new(struct eyeballer **pballer,
|
||||
baller->primary = primary;
|
||||
baller->delay_ms = delay_ms;
|
||||
baller->timeoutms = addr_next_match(baller->addr, baller->ai_family)?
|
||||
timeout_ms / 2 : timeout_ms;
|
||||
USETIME(timeout_ms) : timeout_ms;
|
||||
baller->timeout_id = timeout_id;
|
||||
baller->result = CURLE_COULDNT_CONNECT;
|
||||
|
||||
@@ -475,7 +480,7 @@ static void baller_initiate(struct Curl_cfilter *cf,
|
||||
|
||||
out:
|
||||
if(result) {
|
||||
DEBUGF(LOG_CF(data, cf, "%s failed", baller->name));
|
||||
CURL_TRC_CF(data, cf, "%s failed", baller->name);
|
||||
baller_close(baller, data);
|
||||
}
|
||||
if(cf_prev)
|
||||
@@ -501,7 +506,7 @@ static CURLcode baller_start(struct Curl_cfilter *cf,
|
||||
while(baller->addr) {
|
||||
baller->started = Curl_now();
|
||||
baller->timeoutms = addr_next_match(baller->addr, baller->ai_family) ?
|
||||
timeoutms / 2 : timeoutms;
|
||||
USETIME(timeoutms) : timeoutms;
|
||||
baller_initiate(cf, data, baller);
|
||||
if(!baller->result)
|
||||
break;
|
||||
@@ -601,8 +606,8 @@ evaluate:
|
||||
continue;
|
||||
}
|
||||
baller->result = baller_connect(cf, data, baller, &now, connected);
|
||||
DEBUGF(LOG_CF(data, cf, "%s connect -> %d, connected=%d",
|
||||
baller->name, baller->result, *connected));
|
||||
CURL_TRC_CF(data, cf, "%s connect -> %d, connected=%d",
|
||||
baller->name, baller->result, *connected);
|
||||
|
||||
if(!baller->result) {
|
||||
if(*connected) {
|
||||
@@ -623,11 +628,11 @@ evaluate:
|
||||
}
|
||||
baller_start_next(cf, data, baller, Curl_timeleft(data, &now, TRUE));
|
||||
if(baller->is_done) {
|
||||
DEBUGF(LOG_CF(data, cf, "%s done", baller->name));
|
||||
CURL_TRC_CF(data, cf, "%s done", baller->name);
|
||||
}
|
||||
else {
|
||||
/* next attempt was started */
|
||||
DEBUGF(LOG_CF(data, cf, "%s trying next", baller->name));
|
||||
CURL_TRC_CF(data, cf, "%s trying next", baller->name);
|
||||
++ongoing;
|
||||
}
|
||||
}
|
||||
@@ -661,12 +666,12 @@ evaluate:
|
||||
Curl_timediff(now, ctx->started) >= baller->delay_ms) {
|
||||
baller_start(cf, data, baller, Curl_timeleft(data, &now, TRUE));
|
||||
if(baller->is_done) {
|
||||
DEBUGF(LOG_CF(data, cf, "%s done", baller->name));
|
||||
CURL_TRC_CF(data, cf, "%s done", baller->name);
|
||||
}
|
||||
else {
|
||||
DEBUGF(LOG_CF(data, cf, "%s starting (timeout=%"
|
||||
CURL_FORMAT_TIMEDIFF_T "ms)",
|
||||
baller->name, baller->timeoutms));
|
||||
CURL_TRC_CF(data, cf, "%s starting (timeout=%"
|
||||
CURL_FORMAT_TIMEDIFF_T "ms)",
|
||||
baller->name, baller->timeoutms);
|
||||
++ongoing;
|
||||
++added;
|
||||
}
|
||||
@@ -683,14 +688,14 @@ evaluate:
|
||||
}
|
||||
|
||||
/* all ballers have failed to connect. */
|
||||
DEBUGF(LOG_CF(data, cf, "all eyeballers failed"));
|
||||
CURL_TRC_CF(data, cf, "all eyeballers failed");
|
||||
result = CURLE_COULDNT_CONNECT;
|
||||
for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
|
||||
struct eyeballer *baller = ctx->baller[i];
|
||||
DEBUGF(LOG_CF(data, cf, "%s assess started=%d, result=%d",
|
||||
baller?baller->name:NULL,
|
||||
baller?baller->has_started:0,
|
||||
baller?baller->result:0));
|
||||
CURL_TRC_CF(data, cf, "%s assess started=%d, result=%d",
|
||||
baller?baller->name:NULL,
|
||||
baller?baller->has_started:0,
|
||||
baller?baller->result:0);
|
||||
if(baller && baller->has_started && baller->result) {
|
||||
result = baller->result;
|
||||
break;
|
||||
@@ -803,9 +808,9 @@ static CURLcode start_connect(struct Curl_cfilter *cf,
|
||||
timeout_ms, EXPIRE_DNS_PER_NAME);
|
||||
if(result)
|
||||
return result;
|
||||
DEBUGF(LOG_CF(data, cf, "created %s (timeout %"
|
||||
CURL_FORMAT_TIMEDIFF_T "ms)",
|
||||
ctx->baller[0]->name, ctx->baller[0]->timeoutms));
|
||||
CURL_TRC_CF(data, cf, "created %s (timeout %"
|
||||
CURL_FORMAT_TIMEDIFF_T "ms)",
|
||||
ctx->baller[0]->name, ctx->baller[0]->timeoutms);
|
||||
if(addr1) {
|
||||
/* second one gets a delayed start */
|
||||
result = eyeballer_new(&ctx->baller[1], ctx->cf_create, addr1, ai_family1,
|
||||
@@ -815,9 +820,9 @@ static CURLcode start_connect(struct Curl_cfilter *cf,
|
||||
timeout_ms, EXPIRE_DNS_PER_NAME2);
|
||||
if(result)
|
||||
return result;
|
||||
DEBUGF(LOG_CF(data, cf, "created %s (timeout %"
|
||||
CURL_FORMAT_TIMEDIFF_T "ms)",
|
||||
ctx->baller[1]->name, ctx->baller[1]->timeoutms));
|
||||
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,
|
||||
@@ -931,7 +936,7 @@ static void cf_he_close(struct Curl_cfilter *cf,
|
||||
{
|
||||
struct cf_he_ctx *ctx = cf->ctx;
|
||||
|
||||
DEBUGF(LOG_CF(data, cf, "close"));
|
||||
CURL_TRC_CF(data, cf, "close");
|
||||
cf_he_ctx_clear(cf, data);
|
||||
cf->connected = FALSE;
|
||||
ctx->state = SCFST_INIT;
|
||||
@@ -1007,7 +1012,7 @@ static CURLcode cf_he_query(struct Curl_cfilter *cf,
|
||||
}
|
||||
}
|
||||
*pres1 = reply_ms;
|
||||
DEBUGF(LOG_CF(data, cf, "query connect reply: %dms", *pres1));
|
||||
CURL_TRC_CF(data, cf, "query connect reply: %dms", *pres1);
|
||||
return CURLE_OK;
|
||||
}
|
||||
case CF_QUERY_TIMER_CONNECT: {
|
||||
@@ -1034,7 +1039,7 @@ static void cf_he_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
{
|
||||
struct cf_he_ctx *ctx = cf->ctx;
|
||||
|
||||
DEBUGF(LOG_CF(data, cf, "destroy"));
|
||||
CURL_TRC_CF(data, cf, "destroy");
|
||||
if(ctx) {
|
||||
cf_he_ctx_clear(cf, data);
|
||||
}
|
||||
@@ -1045,7 +1050,7 @@ static void cf_he_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
struct Curl_cftype Curl_cft_happy_eyeballs = {
|
||||
"HAPPY-EYEBALLS",
|
||||
0,
|
||||
CURL_LOG_DEFAULT,
|
||||
CURL_LOG_LVL_NONE,
|
||||
cf_he_destroy,
|
||||
cf_he_connect,
|
||||
cf_he_close,
|
||||
@@ -1148,7 +1153,7 @@ static CURLcode cf_he_insert_after(struct Curl_cfilter *cf_at,
|
||||
DEBUGASSERT(cf_at);
|
||||
cf_create = get_cf_create(transport);
|
||||
if(!cf_create) {
|
||||
DEBUGF(LOG_CF(data, cf_at, "unsupported transport type %d", transport));
|
||||
CURL_TRC_CF(data, cf_at, "unsupported transport type %d", transport);
|
||||
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||
}
|
||||
result = cf_happy_eyeballs_create(&cf, data, cf_at->conn,
|
||||
@@ -1286,7 +1291,7 @@ static void cf_setup_close(struct Curl_cfilter *cf,
|
||||
{
|
||||
struct cf_setup_ctx *ctx = cf->ctx;
|
||||
|
||||
DEBUGF(LOG_CF(data, cf, "close"));
|
||||
CURL_TRC_CF(data, cf, "close");
|
||||
cf->connected = FALSE;
|
||||
ctx->state = CF_SETUP_INIT;
|
||||
|
||||
@@ -1301,7 +1306,7 @@ static void cf_setup_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
struct cf_setup_ctx *ctx = cf->ctx;
|
||||
|
||||
(void)data;
|
||||
DEBUGF(LOG_CF(data, cf, "destroy"));
|
||||
CURL_TRC_CF(data, cf, "destroy");
|
||||
Curl_safefree(ctx);
|
||||
}
|
||||
|
||||
@@ -1309,7 +1314,7 @@ static void cf_setup_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
struct Curl_cftype Curl_cft_setup = {
|
||||
"SETUP",
|
||||
0,
|
||||
CURL_LOG_DEFAULT,
|
||||
CURL_LOG_LVL_NONE,
|
||||
cf_setup_destroy,
|
||||
cf_setup_connect,
|
||||
cf_setup_close,
|
||||
@@ -1441,4 +1446,3 @@ CURLcode Curl_conn_setup(struct Curl_easy *data,
|
||||
out:
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,11 +24,18 @@
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef BUILDING_LIBCURL
|
||||
/* this renames functions so that the tool code can use the same code
|
||||
without getting symbol collisions */
|
||||
#define Curl_base64_encode(a,b,c,d) curlx_base64_encode(a,b,c,d)
|
||||
#define Curl_base64url_encode(a,b,c,d) curlx_base64url_encode(a,b,c,d)
|
||||
#define Curl_base64_decode(a,b,c) curlx_base64_decode(a,b,c)
|
||||
#endif
|
||||
|
||||
CURLcode Curl_base64_encode(const char *inputbuff, size_t insize,
|
||||
char **outptr, size_t *outlen);
|
||||
CURLcode Curl_base64url_encode(const char *inputbuff, size_t insize,
|
||||
char **outptr, size_t *outlen);
|
||||
CURLcode Curl_base64_decode(const char *src,
|
||||
unsigned char **outptr, size_t *outlen);
|
||||
|
||||
#endif /* HEADER_CURL_BASE64_H */
|
||||
|
||||
@@ -25,14 +25,32 @@
|
||||
|
||||
#include <cm3p/kwiml/abi.h>
|
||||
|
||||
/* Default SSL backend */
|
||||
#cmakedefine CURL_DEFAULT_SSL_BACKEND "${CURL_DEFAULT_SSL_BACKEND}"
|
||||
|
||||
/* disables alt-svc */
|
||||
#cmakedefine CURL_DISABLE_ALTSVC 1
|
||||
|
||||
/* disables cookies support */
|
||||
#cmakedefine CURL_DISABLE_COOKIES 1
|
||||
|
||||
/* disables cryptographic authentication */
|
||||
#cmakedefine CURL_DISABLE_CRYPTO_AUTH 1
|
||||
/* disables Basic authentication */
|
||||
#cmakedefine CURL_DISABLE_BASIC_AUTH 1
|
||||
|
||||
/* disables Bearer authentication */
|
||||
#cmakedefine CURL_DISABLE_BEARER_AUTH 1
|
||||
|
||||
/* disables Digest authentication */
|
||||
#cmakedefine CURL_DISABLE_DIGEST_AUTH 1
|
||||
|
||||
/* disables Kerberos authentication */
|
||||
#cmakedefine CURL_DISABLE_KERBEROS_AUTH 1
|
||||
|
||||
/* disables negotiate authentication */
|
||||
#cmakedefine CURL_DISABLE_NEGOTIATE_AUTH 1
|
||||
|
||||
/* disables AWS-SIG4 */
|
||||
#cmakedefine CURL_DISABLE_AWS 1
|
||||
|
||||
/* disables DICT */
|
||||
#cmakedefine CURL_DISABLE_DICT 1
|
||||
@@ -43,6 +61,9 @@
|
||||
/* disables FILE */
|
||||
#cmakedefine CURL_DISABLE_FILE 1
|
||||
|
||||
/* disables form api */
|
||||
#cmakedefine CURL_DISABLE_FORM_API 1
|
||||
|
||||
/* disables FTP */
|
||||
#cmakedefine CURL_DISABLE_FTP 1
|
||||
|
||||
@@ -125,12 +146,6 @@
|
||||
/* Use Windows LDAP implementation */
|
||||
#cmakedefine USE_WIN32_LDAP 1
|
||||
|
||||
/* when not building a shared library */
|
||||
#cmakedefine CURL_STATICLIB 1
|
||||
|
||||
/* your Entropy Gathering Daemon socket pathname */
|
||||
#cmakedefine EGD_SOCKET ${EGD_SOCKET}
|
||||
|
||||
/* Define if you want to enable IPv6 support */
|
||||
#cmakedefine ENABLE_IPV6 1
|
||||
|
||||
@@ -392,8 +407,8 @@
|
||||
/* Define to 1 if you have the <pwd.h> header file. */
|
||||
#cmakedefine HAVE_PWD_H 1
|
||||
|
||||
/* Define to 1 if you have the `RAND_egd' function. */
|
||||
#cmakedefine HAVE_RAND_EGD 1
|
||||
/* Define to 1 if OpenSSL has the `SSL_set0_wbio` function. */
|
||||
#cmakedefine HAVE_SSL_SET0_WBIO 1
|
||||
|
||||
/* Define to 1 if you have the recv function. */
|
||||
#cmakedefine HAVE_RECV 1
|
||||
@@ -455,9 +470,6 @@
|
||||
/* Define to 1 if you have the socketpair function. */
|
||||
#cmakedefine HAVE_SOCKETPAIR 1
|
||||
|
||||
/* Define to 1 if you have the <ssl.h> header file. */
|
||||
#cmakedefine HAVE_SSL_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdatomic.h> header file. */
|
||||
#cmakedefine HAVE_STDATOMIC_H 1
|
||||
|
||||
@@ -643,6 +655,9 @@
|
||||
# define SIZEOF___INT64 KWIML_ABI_SIZEOF___INT64
|
||||
#endif
|
||||
|
||||
/* The size of `long long', as computed by sizeof. */
|
||||
${SIZEOF_LONG_LONG_CODE}
|
||||
|
||||
/* The size of `off_t', as computed by sizeof. */
|
||||
${SIZEOF_OFF_T_CODE}
|
||||
|
||||
@@ -700,12 +715,6 @@ ${SIZEOF_TIME_T_CODE}
|
||||
/* If you want to build curl with the built-in manual */
|
||||
#cmakedefine USE_MANUAL 1
|
||||
|
||||
/* if NSS is enabled */
|
||||
#cmakedefine USE_NSS 1
|
||||
|
||||
/* if you have the PK11_CreateManagedGenericObject function */
|
||||
#cmakedefine HAVE_PK11_CREATEMANAGEDGENERICOBJECT 1
|
||||
|
||||
/* if you want to use OpenLDAP code instead of legacy ldap implementation */
|
||||
#cmakedefine USE_OPENLDAP 1
|
||||
|
||||
|
||||
@@ -24,12 +24,11 @@
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#if defined(USE_CURL_NTLM_CORE) && !defined(USE_WOLFSSL) && \
|
||||
(defined(USE_GNUTLS) || \
|
||||
defined(USE_NSS) || \
|
||||
defined(USE_SECTRANSP) || \
|
||||
defined(USE_OS400CRYPTO) || \
|
||||
defined(USE_WIN32_CRYPTO))
|
||||
#if defined(USE_CURL_NTLM_CORE) && !defined(USE_WOLFSSL) && \
|
||||
(defined(USE_GNUTLS) || \
|
||||
defined(USE_SECTRANSP) || \
|
||||
defined(USE_OS400CRYPTO) || \
|
||||
defined(USE_WIN32_CRYPTO))
|
||||
|
||||
#include "curl_des.h"
|
||||
|
||||
|
||||
@@ -26,12 +26,11 @@
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#if defined(USE_CURL_NTLM_CORE) && !defined(USE_WOLFSSL) && \
|
||||
(defined(USE_GNUTLS) || \
|
||||
defined(USE_NSS) || \
|
||||
defined(USE_SECTRANSP) || \
|
||||
defined(USE_OS400CRYPTO) || \
|
||||
defined(USE_WIN32_CRYPTO))
|
||||
#if defined(USE_CURL_NTLM_CORE) && !defined(USE_WOLFSSL) && \
|
||||
(defined(USE_GNUTLS) || \
|
||||
defined(USE_SECTRANSP) || \
|
||||
defined(USE_OS400CRYPTO) || \
|
||||
defined(USE_WIN32_CRYPTO))
|
||||
|
||||
/* Applies odd parity to the given byte array */
|
||||
void Curl_des_set_odd_parity(unsigned char *bytes, size_t length);
|
||||
|
||||
@@ -24,7 +24,8 @@
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||
#if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI)) \
|
||||
|| !defined(CURL_DISABLE_AWS)
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
#ifndef HEADER_CURL_LOG_H
|
||||
#define HEADER_CURL_LOG_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* SPDX-License-Identifier: curl
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
struct Curl_easy;
|
||||
struct Curl_cfilter;
|
||||
|
||||
/**
|
||||
* Init logging, return != 0 on failure.
|
||||
*/
|
||||
CURLcode Curl_log_init(void);
|
||||
|
||||
|
||||
void Curl_infof(struct Curl_easy *, const char *fmt, ...);
|
||||
void Curl_failf(struct Curl_easy *, const char *fmt, ...);
|
||||
|
||||
#if defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
|
||||
#if defined(HAVE_VARIADIC_MACROS_C99)
|
||||
#define infof(...) Curl_nop_stmt
|
||||
#elif defined(HAVE_VARIADIC_MACROS_GCC)
|
||||
#define infof(x...) Curl_nop_stmt
|
||||
#else
|
||||
#error "missing VARIADIC macro define, fix and rebuild!"
|
||||
#endif
|
||||
|
||||
#else /* CURL_DISABLE_VERBOSE_STRINGS */
|
||||
|
||||
#define infof Curl_infof
|
||||
|
||||
#endif /* CURL_DISABLE_VERBOSE_STRINGS */
|
||||
|
||||
#define failf Curl_failf
|
||||
|
||||
|
||||
#define CURL_LOG_DEFAULT 0
|
||||
#define CURL_LOG_DEBUG 1
|
||||
#define CURL_LOG_TRACE 2
|
||||
|
||||
|
||||
/* the function used to output verbose information */
|
||||
void Curl_debug(struct Curl_easy *data, curl_infotype type,
|
||||
char *ptr, size_t size);
|
||||
|
||||
#ifdef DEBUGBUILD
|
||||
|
||||
/* explainer: we have some mix configuration and werror settings
|
||||
* that define HAVE_VARIADIC_MACROS_C99 even though C89 is enforced
|
||||
* on gnuc and some other compiler. Need to treat carefully.
|
||||
*/
|
||||
#if defined(HAVE_VARIADIC_MACROS_C99) && \
|
||||
defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
|
||||
|
||||
#define LOG_CF(data, cf, ...) \
|
||||
do { if(Curl_log_cf_is_debug(cf, data)) \
|
||||
Curl_log_cf_debug(data, cf, __VA_ARGS__); } while(0)
|
||||
#else
|
||||
#define LOG_CF Curl_log_cf_debug
|
||||
#endif
|
||||
|
||||
void Curl_log_cf_debug(struct Curl_easy *data, struct Curl_cfilter *cf,
|
||||
#if defined(__GNUC__) && !defined(printf) && \
|
||||
defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
|
||||
!defined(__MINGW32__)
|
||||
const char *fmt, ...)
|
||||
__attribute__((format(printf, 3, 4)));
|
||||
#else
|
||||
const char *fmt, ...);
|
||||
#endif
|
||||
|
||||
#define Curl_log_cf_is_debug(cf, data) \
|
||||
((data) && (data)->set.verbose && \
|
||||
(cf) && (cf)->cft->log_level >= CURL_LOG_DEBUG)
|
||||
|
||||
|
||||
#else /* !DEBUGBUILD */
|
||||
|
||||
#if defined(HAVE_VARIADIC_MACROS_C99) && \
|
||||
defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
|
||||
#define LOG_CF(...) Curl_nop_stmt
|
||||
#define Curl_log_cf_debug(...) Curl_nop_stmt
|
||||
#elif defined(HAVE_VARIADIC_MACROS_GCC) && \
|
||||
defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
|
||||
#define LOG_CF(x...) Curl_nop_stmt
|
||||
#define Curl_log_cf_debug(x...) Curl_nop_stmt
|
||||
#else
|
||||
#define LOG_CF Curl_log_cf_debug
|
||||
/* without c99, we seem unable to completely define away this function. */
|
||||
void Curl_log_cf_debug(struct Curl_easy *data, struct Curl_cfilter *cf,
|
||||
const char *fmt, ...);
|
||||
#endif
|
||||
|
||||
#define Curl_log_cf_is_debug(x,y) ((void)(x), (void)(y), FALSE)
|
||||
|
||||
#endif /* !DEBUGBUILD */
|
||||
|
||||
#define LOG_CF_IS_DEBUG(cf, data) Curl_log_cf_is_debug(cf, data)
|
||||
|
||||
#endif /* HEADER_CURL_LOG_H */
|
||||
@@ -25,14 +25,15 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include "curl_setup.h"
|
||||
#include <curl/curl.h>
|
||||
|
||||
#if !defined(CURL_DISABLE_CRYPTO_AUTH)
|
||||
#if defined(USE_CURL_NTLM_CORE)
|
||||
|
||||
#define MD4_DIGEST_LENGTH 16
|
||||
|
||||
void Curl_md4it(unsigned char *output, const unsigned char *input,
|
||||
const size_t len);
|
||||
CURLcode Curl_md4it(unsigned char *output, const unsigned char *input,
|
||||
const size_t len);
|
||||
|
||||
#endif /* !defined(CURL_DISABLE_CRYPTO_AUTH) */
|
||||
#endif /* defined(USE_CURL_NTLM_CORE) */
|
||||
|
||||
#endif /* HEADER_CURL_MD4_H */
|
||||
|
||||
@@ -24,7 +24,9 @@
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||
#if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI)) \
|
||||
|| !defined(CURL_DISABLE_DIGEST_AUTH)
|
||||
|
||||
#include "curl_hmac.h"
|
||||
|
||||
#define MD5_DIGEST_LEN 16
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
1. USE_OPENSSL
|
||||
2. USE_WOLFSSL
|
||||
3. USE_GNUTLS
|
||||
4. USE_NSS
|
||||
4. -
|
||||
5. USE_MBEDTLS
|
||||
6. USE_SECTRANSP
|
||||
7. USE_OS400CRYPTO
|
||||
@@ -47,7 +47,7 @@
|
||||
This ensures that:
|
||||
- the same SSL branch gets activated throughout this source
|
||||
file even if multiple backends are enabled at the same time.
|
||||
- OpenSSL and NSS have higher priority than Windows Crypt, due
|
||||
- OpenSSL has higher priority than Windows Crypt, due
|
||||
to issues with the latter supporting NTLM2Session responses
|
||||
in NTLM type-3 messages.
|
||||
*/
|
||||
@@ -96,12 +96,6 @@
|
||||
|
||||
# include <nettle/des.h>
|
||||
|
||||
#elif defined(USE_NSS)
|
||||
|
||||
# include <nss.h>
|
||||
# include <pk11pub.h>
|
||||
# include <hasht.h>
|
||||
|
||||
#elif defined(USE_MBEDTLS)
|
||||
|
||||
# include <mbedtls/des.h>
|
||||
@@ -188,70 +182,6 @@ static void setup_des_key(const unsigned char *key_56,
|
||||
des_set_key(des, (const uint8_t *) key);
|
||||
}
|
||||
|
||||
#elif defined(USE_NSS)
|
||||
|
||||
/*
|
||||
* encrypt_des() expands a 56 bit key KEY_56 to 64 bit and encrypts 64 bit of
|
||||
* data, using the expanded key. IN should point to 64 bits of source data,
|
||||
* OUT to a 64 bit output buffer.
|
||||
*/
|
||||
static bool encrypt_des(const unsigned char *in, unsigned char *out,
|
||||
const unsigned char *key_56)
|
||||
{
|
||||
const CK_MECHANISM_TYPE mech = CKM_DES_ECB; /* DES cipher in ECB mode */
|
||||
char key[8]; /* expanded 64 bit key */
|
||||
SECItem key_item;
|
||||
PK11SymKey *symkey = NULL;
|
||||
SECItem *param = NULL;
|
||||
PK11Context *ctx = NULL;
|
||||
int out_len; /* not used, required by NSS */
|
||||
bool rv = FALSE;
|
||||
|
||||
/* use internal slot for DES encryption (requires NSS to be initialized) */
|
||||
PK11SlotInfo *slot = PK11_GetInternalKeySlot();
|
||||
if(!slot)
|
||||
return FALSE;
|
||||
|
||||
/* Expand the 56-bit key to 64-bits */
|
||||
extend_key_56_to_64(key_56, key);
|
||||
|
||||
/* Set the key parity to odd */
|
||||
Curl_des_set_odd_parity((unsigned char *) key, sizeof(key));
|
||||
|
||||
/* Import the key */
|
||||
key_item.data = (unsigned char *)key;
|
||||
key_item.len = sizeof(key);
|
||||
symkey = PK11_ImportSymKey(slot, mech, PK11_OriginUnwrap, CKA_ENCRYPT,
|
||||
&key_item, NULL);
|
||||
if(!symkey)
|
||||
goto fail;
|
||||
|
||||
/* Create the DES encryption context */
|
||||
param = PK11_ParamFromIV(mech, /* no IV in ECB mode */ NULL);
|
||||
if(!param)
|
||||
goto fail;
|
||||
ctx = PK11_CreateContextBySymKey(mech, CKA_ENCRYPT, symkey, param);
|
||||
if(!ctx)
|
||||
goto fail;
|
||||
|
||||
/* Perform the encryption */
|
||||
if(SECSuccess == PK11_CipherOp(ctx, out, &out_len, /* outbuflen */ 8,
|
||||
(unsigned char *)in, /* inbuflen */ 8)
|
||||
&& SECSuccess == PK11_Finalize(ctx))
|
||||
rv = /* all OK */ TRUE;
|
||||
|
||||
fail:
|
||||
/* cleanup */
|
||||
if(ctx)
|
||||
PK11_DestroyContext(ctx, PR_TRUE);
|
||||
if(symkey)
|
||||
PK11_FreeSymKey(symkey);
|
||||
if(param)
|
||||
SECITEM_FreeItem(param, PR_TRUE);
|
||||
PK11_FreeSlot(slot);
|
||||
return rv;
|
||||
}
|
||||
|
||||
#elif defined(USE_MBEDTLS)
|
||||
|
||||
static bool encrypt_des(const unsigned char *in, unsigned char *out,
|
||||
@@ -402,7 +332,7 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys,
|
||||
des_encrypt(&des, 8, results + 8, plaintext);
|
||||
setup_des_key(keys + 14, &des);
|
||||
des_encrypt(&des, 8, results + 16, plaintext);
|
||||
#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_SECTRANSP) \
|
||||
#elif defined(USE_MBEDTLS) || defined(USE_SECTRANSP) \
|
||||
|| defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
|
||||
encrypt_des(plaintext, results, keys);
|
||||
encrypt_des(plaintext, results + 8, keys + 7);
|
||||
@@ -444,7 +374,7 @@ CURLcode Curl_ntlm_core_mk_lm_hash(const char *password,
|
||||
des_encrypt(&des, 8, lmbuffer, magic);
|
||||
setup_des_key(pw + 7, &des);
|
||||
des_encrypt(&des, 8, lmbuffer + 8, magic);
|
||||
#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_SECTRANSP) \
|
||||
#elif defined(USE_MBEDTLS) || defined(USE_SECTRANSP) \
|
||||
|| defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
|
||||
encrypt_des(magic, lmbuffer, pw);
|
||||
encrypt_des(magic, lmbuffer + 8, pw + 7);
|
||||
@@ -489,6 +419,7 @@ CURLcode Curl_ntlm_core_mk_nt_hash(const char *password,
|
||||
{
|
||||
size_t len = strlen(password);
|
||||
unsigned char *pw;
|
||||
CURLcode result;
|
||||
if(len > SIZE_T_MAX/2) /* avoid integer overflow */
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
pw = len ? malloc(len * 2) : (unsigned char *)strdup("");
|
||||
@@ -498,12 +429,13 @@ CURLcode Curl_ntlm_core_mk_nt_hash(const char *password,
|
||||
ascii_to_unicode_le(pw, password, len);
|
||||
|
||||
/* Create NT hashed password. */
|
||||
Curl_md4it(ntbuffer, pw, 2 * len);
|
||||
memset(ntbuffer + 16, 0, 21 - 16);
|
||||
result = Curl_md4it(ntbuffer, pw, 2 * len);
|
||||
if(!result)
|
||||
memset(ntbuffer + 16, 0, 21 - 16);
|
||||
|
||||
free(pw);
|
||||
|
||||
return CURLE_OK;
|
||||
return result;
|
||||
}
|
||||
|
||||
#if !defined(USE_WINDOWS_SSPI)
|
||||
|
||||
@@ -28,15 +28,6 @@
|
||||
|
||||
#if defined(USE_CURL_NTLM_CORE)
|
||||
|
||||
/* If NSS is the first available SSL backend (see order in curl_ntlm_core.c)
|
||||
then it must be initialized to be used by NTLM. */
|
||||
#if !defined(USE_OPENSSL) && \
|
||||
!defined(USE_WOLFSSL) && \
|
||||
!defined(USE_GNUTLS) && \
|
||||
defined(USE_NSS)
|
||||
#define NTLM_NEEDS_NSS_INIT
|
||||
#endif
|
||||
|
||||
#if defined(USE_OPENSSL)
|
||||
# include <openssl/ssl.h>
|
||||
#elif defined(USE_WOLFSSL)
|
||||
|
||||
@@ -420,7 +420,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||
#ifndef CURL_DISABLE_DIGEST_AUTH
|
||||
if((enabledmechs & SASL_MECH_DIGEST_MD5) &&
|
||||
Curl_auth_is_digest_supported()) {
|
||||
mech = SASL_MECH_STRING_DIGEST_MD5;
|
||||
@@ -530,8 +530,8 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
|
||||
struct bufref resp;
|
||||
const char *hostname, *disp_hostname;
|
||||
int port;
|
||||
#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
|
||||
defined(USE_NTLM)
|
||||
#if defined(USE_KERBEROS5) || defined(USE_NTLM) \
|
||||
|| !defined(CURL_DISABLE_DIGEST_AUTH)
|
||||
const char *service = data->set.str[STRING_SERVICE_NAME] ?
|
||||
data->set.str[STRING_SERVICE_NAME] :
|
||||
sasl->params->service;
|
||||
@@ -577,7 +577,6 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
|
||||
case SASL_EXTERNAL:
|
||||
result = Curl_auth_create_external_message(conn->user, &resp);
|
||||
break;
|
||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||
#ifdef USE_GSASL
|
||||
case SASL_GSASL:
|
||||
result = get_server_message(sasl, data, &serverdata);
|
||||
@@ -587,6 +586,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
|
||||
newstate = SASL_GSASL;
|
||||
break;
|
||||
#endif
|
||||
#ifndef CURL_DISABLE_DIGEST_AUTH
|
||||
case SASL_CRAMMD5:
|
||||
result = get_server_message(sasl, data, &serverdata);
|
||||
if(!result)
|
||||
|
||||
@@ -262,8 +262,9 @@
|
||||
#if defined(__APPLE__) && !defined(USE_ARES)
|
||||
#include <TargetConditionals.h>
|
||||
#define USE_RESOLVE_ON_IPS 1
|
||||
# if !defined(TARGET_OS_OSX) || TARGET_OS_OSX
|
||||
# define CURL_OSX_CALL_COPYPROXIES 1
|
||||
# if TARGET_OS_MAC && !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) && \
|
||||
defined(ENABLE_IPV6)
|
||||
# define CURL_MACOS_CALL_COPYPROXIES 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
@@ -659,32 +660,30 @@
|
||||
|
||||
#define LIBIDN_REQUIRED_VERSION "0.4.1"
|
||||
|
||||
#if defined(USE_GNUTLS) || defined(USE_OPENSSL) || defined(USE_NSS) || \
|
||||
defined(USE_MBEDTLS) || \
|
||||
defined(USE_WOLFSSL) || defined(USE_SCHANNEL) || \
|
||||
defined(USE_SECTRANSP) || defined(USE_GSKIT) || \
|
||||
defined(USE_BEARSSL) || defined(USE_RUSTLS)
|
||||
#if defined(USE_GNUTLS) || defined(USE_OPENSSL) || defined(USE_MBEDTLS) || \
|
||||
defined(USE_WOLFSSL) || defined(USE_SCHANNEL) || defined(USE_SECTRANSP) || \
|
||||
defined(USE_BEARSSL) || defined(USE_RUSTLS)
|
||||
#define USE_SSL /* SSL support has been enabled */
|
||||
#endif
|
||||
|
||||
/* Single point where USE_SPNEGO definition might be defined */
|
||||
#if !defined(CURL_DISABLE_CRYPTO_AUTH) && \
|
||||
#if !defined(CURL_DISABLE_NEGOTIATE_AUTH) && \
|
||||
(defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI))
|
||||
#define USE_SPNEGO
|
||||
#endif
|
||||
|
||||
/* Single point where USE_KERBEROS5 definition might be defined */
|
||||
#if !defined(CURL_DISABLE_CRYPTO_AUTH) && \
|
||||
#if !defined(CURL_DISABLE_KERBEROS_AUTH) && \
|
||||
(defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI))
|
||||
#define USE_KERBEROS5
|
||||
#endif
|
||||
|
||||
/* Single point where USE_NTLM definition might be defined */
|
||||
#if !defined(CURL_DISABLE_CRYPTO_AUTH) && !defined(CURL_DISABLE_NTLM)
|
||||
# if defined(USE_OPENSSL) || defined(USE_MBEDTLS) || \
|
||||
defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_SECTRANSP) || \
|
||||
defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || \
|
||||
(defined(USE_WOLFSSL) && defined(HAVE_WOLFSSL_DES_ECB_ENCRYPT))
|
||||
#if !defined(CURL_DISABLE_NTLM)
|
||||
# if defined(USE_OPENSSL) || defined(USE_MBEDTLS) || \
|
||||
defined(USE_GNUTLS) || defined(USE_SECTRANSP) || \
|
||||
defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || \
|
||||
(defined(USE_WOLFSSL) && defined(HAVE_WOLFSSL_DES_ECB_ENCRYPT))
|
||||
# define USE_CURL_NTLM_CORE
|
||||
# endif
|
||||
# if defined(USE_CURL_NTLM_CORE) || defined(USE_WINDOWS_SSPI)
|
||||
|
||||
@@ -25,7 +25,9 @@
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||
#if !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH) \
|
||||
|| defined(USE_LIBSSH2)
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include "curl_hmac.h"
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "curl_log.h"
|
||||
#include "curl_trc.h"
|
||||
#include "urldata.h"
|
||||
#include "easyif.h"
|
||||
#include "cfilters.h"
|
||||
@@ -124,13 +124,13 @@ void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUGBUILD
|
||||
#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
|
||||
void Curl_log_cf_debug(struct Curl_easy *data, struct Curl_cfilter *cf,
|
||||
void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
DEBUGASSERT(cf);
|
||||
if(data && Curl_log_cf_is_debug(cf, data)) {
|
||||
if(data && Curl_trc_cf_is_verbose(cf, data)) {
|
||||
va_list ap;
|
||||
int len;
|
||||
char buffer[MAXINFO + 2];
|
||||
@@ -179,44 +179,67 @@ static struct Curl_cftype *cf_types[] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
#ifndef ARRAYSIZE
|
||||
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
|
||||
#endif
|
||||
|
||||
CURLcode Curl_log_init(void)
|
||||
CURLcode Curl_trc_opt(const char *config)
|
||||
{
|
||||
const char *setting = getenv("CURL_DEBUG");
|
||||
if(setting) {
|
||||
char *token, *tok_buf, *tmp;
|
||||
size_t i;
|
||||
char *token, *tok_buf, *tmp;
|
||||
size_t i;
|
||||
int lvl;
|
||||
|
||||
tmp = strdup(setting);
|
||||
if(!tmp)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
tmp = strdup(config);
|
||||
if(!tmp)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
token = strtok_r(tmp, ", ", &tok_buf);
|
||||
while(token) {
|
||||
for(i = 0; cf_types[i]; ++i) {
|
||||
if(strcasecompare(token, cf_types[i]->name)) {
|
||||
cf_types[i]->log_level = CURL_LOG_DEBUG;
|
||||
break;
|
||||
}
|
||||
}
|
||||
token = strtok_r(NULL, ", ", &tok_buf);
|
||||
token = strtok_r(tmp, ", ", &tok_buf);
|
||||
while(token) {
|
||||
switch(*token) {
|
||||
case '-':
|
||||
lvl = CURL_LOG_LVL_NONE;
|
||||
++token;
|
||||
break;
|
||||
case '+':
|
||||
lvl = CURL_LOG_LVL_INFO;
|
||||
++token;
|
||||
break;
|
||||
default:
|
||||
lvl = CURL_LOG_LVL_INFO;
|
||||
break;
|
||||
}
|
||||
free(tmp);
|
||||
for(i = 0; cf_types[i]; ++i) {
|
||||
if(strcasecompare(token, "all")) {
|
||||
cf_types[i]->log_level = lvl;
|
||||
}
|
||||
else if(strcasecompare(token, cf_types[i]->name)) {
|
||||
cf_types[i]->log_level = lvl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
token = strtok_r(NULL, ", ", &tok_buf);
|
||||
}
|
||||
free(tmp);
|
||||
return CURLE_OK;
|
||||
}
|
||||
#else /* DEBUGBUILD */
|
||||
|
||||
CURLcode Curl_log_init(void)
|
||||
CURLcode Curl_trc_init(void)
|
||||
{
|
||||
#ifdef DEBUGBUILD
|
||||
/* WIP: we use the auto-init from an env var only in DEBUG builds for
|
||||
* convenience. */
|
||||
const char *config = getenv("CURL_DEBUG");
|
||||
if(config) {
|
||||
return Curl_trc_opt(config);
|
||||
}
|
||||
#endif
|
||||
return CURLE_OK;
|
||||
}
|
||||
#else /* !CURL_DISABLE_VERBOSE_STRINGS) */
|
||||
|
||||
CURLcode Curl_trc_init(void)
|
||||
{
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
|
||||
void Curl_log_cf_debug(struct Curl_easy *data, struct Curl_cfilter *cf,
|
||||
void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
(void)data;
|
||||
@@ -0,0 +1,150 @@
|
||||
#ifndef HEADER_CURL_TRC_H
|
||||
#define HEADER_CURL_TRC_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* SPDX-License-Identifier: curl
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
struct Curl_easy;
|
||||
struct Curl_cfilter;
|
||||
|
||||
/**
|
||||
* Init logging, return != 0 on failure.
|
||||
*/
|
||||
CURLcode Curl_trc_init(void);
|
||||
|
||||
/**
|
||||
* Configure tracing. May be called several times during global
|
||||
* initialization. Later calls may not take effect.
|
||||
*
|
||||
* Configuration format supported:
|
||||
* - comma-separated list of component names to enable logging on.
|
||||
* E.g. 'http/2,ssl'. Unknown names are ignored. Names are compared
|
||||
* case-insensitive.
|
||||
* - component 'all' applies to all known log components
|
||||
* - prefixing a component with '+' or '-' will en-/disable logging for
|
||||
* that component
|
||||
* Example: 'all,-ssl' would enable logging for all components but the
|
||||
* SSL filters.
|
||||
*
|
||||
* @param config configuration string
|
||||
*/
|
||||
CURLcode Curl_trc_opt(const char *config);
|
||||
|
||||
/* the function used to output verbose information */
|
||||
void Curl_debug(struct Curl_easy *data, curl_infotype type,
|
||||
char *ptr, size_t size);
|
||||
|
||||
/**
|
||||
* Output an informational message when transfer's verbose logging is enabled.
|
||||
*/
|
||||
void Curl_infof(struct Curl_easy *data,
|
||||
#if defined(__GNUC__) && !defined(printf) && \
|
||||
defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
|
||||
!defined(__MINGW32__)
|
||||
const char *fmt, ...)
|
||||
__attribute__((format(printf, 2, 3)));
|
||||
#else
|
||||
const char *fmt, ...);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Output a failure message on registered callbacks for transfer.
|
||||
*/
|
||||
void Curl_failf(struct Curl_easy *data,
|
||||
#if defined(__GNUC__) && !defined(printf) && \
|
||||
defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
|
||||
!defined(__MINGW32__)
|
||||
const char *fmt, ...)
|
||||
__attribute__((format(printf, 2, 3)));
|
||||
#else
|
||||
const char *fmt, ...);
|
||||
#endif
|
||||
|
||||
#define failf Curl_failf
|
||||
|
||||
/**
|
||||
* Output an informational message when both transfer's verbose logging
|
||||
* and connection filters verbose logging are enabled.
|
||||
*/
|
||||
void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
|
||||
#if defined(__GNUC__) && !defined(printf) && \
|
||||
defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
|
||||
!defined(__MINGW32__)
|
||||
const char *fmt, ...)
|
||||
__attribute__((format(printf, 3, 4)));
|
||||
#else
|
||||
const char *fmt, ...);
|
||||
#endif
|
||||
|
||||
#define CURL_LOG_LVL_NONE 0
|
||||
#define CURL_LOG_LVL_INFO 1
|
||||
|
||||
|
||||
#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
/* informational messages enabled */
|
||||
|
||||
#define Curl_trc_is_verbose(data) ((data) && (data)->set.verbose)
|
||||
#define Curl_trc_cf_is_verbose(cf, data) \
|
||||
((data) && (data)->set.verbose && \
|
||||
(cf) && (cf)->cft->log_level >= CURL_LOG_LVL_INFO)
|
||||
|
||||
/* explainer: we have some mix configuration and werror settings
|
||||
* that define HAVE_VARIADIC_MACROS_C99 even though C89 is enforced
|
||||
* on gnuc and some other compiler. Need to treat carefully.
|
||||
*/
|
||||
#if defined(HAVE_VARIADIC_MACROS_C99) && \
|
||||
defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
|
||||
|
||||
#define infof(data, ...) \
|
||||
do { if(Curl_trc_is_verbose(data)) \
|
||||
Curl_infof(data, __VA_ARGS__); } while(0)
|
||||
#define CURL_TRC_CF(data, cf, ...) \
|
||||
do { if(Curl_trc_cf_is_verbose(cf, data)) \
|
||||
Curl_trc_cf_infof(data, cf, __VA_ARGS__); } while(0)
|
||||
|
||||
#else /* no variadic macro args */
|
||||
#define infof Curl_infof
|
||||
#define CURL_TRC_CF Curl_trc_cf_infof
|
||||
#endif /* variadic macro args */
|
||||
|
||||
#else /* !CURL_DISABLE_VERBOSE_STRINGS */
|
||||
/* All informational messages are not compiled in for size savings */
|
||||
|
||||
#define Curl_trc_is_verbose(d) ((void)(d), FALSE)
|
||||
#define Curl_trc_cf_is_verbose(x,y) ((void)(x), (void)(y), FALSE)
|
||||
|
||||
#if defined(HAVE_VARIADIC_MACROS_C99)
|
||||
#define infof(...) Curl_nop_stmt
|
||||
#define CURL_TRC_CF(...) Curl_nop_stmt
|
||||
#define Curl_trc_cf_infof(...) Curl_nop_stmt
|
||||
#elif defined(HAVE_VARIADIC_MACROS_GCC)
|
||||
#define infof(x...) Curl_nop_stmt
|
||||
#define CURL_TRC_CF(x...) Curl_nop_stmt
|
||||
#define Curl_trc_cf_infof(x...) Curl_nop_stmt
|
||||
#else
|
||||
#error "missing VARIADIC macro define, fix and rebuild!"
|
||||
#endif
|
||||
|
||||
#endif /* CURL_DISABLE_VERBOSE_STRINGS */
|
||||
|
||||
#endif /* HEADER_CURL_TRC_H */
|
||||
@@ -158,8 +158,8 @@ static CURLcode global_init(long flags, bool memoryfuncs)
|
||||
#endif
|
||||
}
|
||||
|
||||
if(Curl_log_init()) {
|
||||
DEBUGF(fprintf(stderr, "Error: Curl_log_init failed\n"));
|
||||
if(Curl_trc_init()) {
|
||||
DEBUGF(fprintf(stderr, "Error: Curl_trc_init failed\n"));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -168,19 +168,15 @@ static CURLcode global_init(long flags, bool memoryfuncs)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
if(Curl_win32_init(flags)) {
|
||||
DEBUGF(fprintf(stderr, "Error: win32_init failed\n"));
|
||||
goto fail;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __AMIGA__
|
||||
if(Curl_amiga_init()) {
|
||||
DEBUGF(fprintf(stderr, "Error: Curl_amiga_init failed\n"));
|
||||
goto fail;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(Curl_macos_init()) {
|
||||
DEBUGF(fprintf(stderr, "Error: Curl_macos_init failed\n"));
|
||||
@@ -319,6 +315,26 @@ void curl_global_cleanup(void)
|
||||
global_init_unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* curl_global_trace() globally initializes curl logging.
|
||||
*/
|
||||
CURLcode curl_global_trace(const char *config)
|
||||
{
|
||||
#ifndef CURL_DISABLE_VERBOSE_STRINGS
|
||||
CURLcode result;
|
||||
global_init_lock();
|
||||
|
||||
result = Curl_trc_opt(config);
|
||||
|
||||
global_init_unlock();
|
||||
|
||||
return result;
|
||||
#else
|
||||
(void)config;
|
||||
return CURLE_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* curl_global_sslset() globally initializes the SSL backend to use.
|
||||
*/
|
||||
@@ -699,7 +715,7 @@ static CURLcode easy_transfer(struct Curl_multi *multi)
|
||||
*
|
||||
* REALITY: it can't just create and destroy the multi handle that easily. It
|
||||
* needs to keep it around since if this easy handle is used again by this
|
||||
* function, the same multi handle must be re-used so that the same pools and
|
||||
* function, the same multi handle must be reused so that the same pools and
|
||||
* caches can be used.
|
||||
*
|
||||
* DEBUG: if 'events' is set TRUE, this function will use a replacement engine
|
||||
@@ -1048,7 +1064,7 @@ void curl_easy_reset(struct Curl_easy *data)
|
||||
memset(&data->state.authhost, 0, sizeof(struct auth));
|
||||
memset(&data->state.authproxy, 0, sizeof(struct auth));
|
||||
|
||||
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
|
||||
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_DIGEST_AUTH)
|
||||
Curl_http_auth_cleanup_digest(data);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "formdata.h"
|
||||
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_MIME)
|
||||
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_FORM_API)
|
||||
|
||||
#if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
|
||||
#include <libgen.h>
|
||||
@@ -941,7 +941,7 @@ int curl_formget(struct curl_httppost *form, void *arg,
|
||||
void curl_formfree(struct curl_httppost *form)
|
||||
{
|
||||
(void)form;
|
||||
/* does nothing HTTP is disabled */
|
||||
/* Nothing to do. */
|
||||
}
|
||||
|
||||
#endif /* if disabled */
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#ifndef CURL_DISABLE_MIME
|
||||
#ifndef CURL_DISABLE_FORM_API
|
||||
|
||||
/* used by FormAdd for temporary storage */
|
||||
struct FormInfo {
|
||||
@@ -53,10 +53,7 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
|
||||
curl_mimepart *,
|
||||
struct curl_httppost *post,
|
||||
curl_read_callback fread_func);
|
||||
#else
|
||||
/* disabled */
|
||||
#define Curl_getformdata(a,b,c,d) CURLE_NOT_BUILT_IN
|
||||
#endif
|
||||
#endif /* CURL_DISABLE_FORM_API */
|
||||
|
||||
|
||||
#endif /* HEADER_CURL_FORMDATA_H */
|
||||
|
||||
@@ -32,9 +32,6 @@
|
||||
#ifdef HAVE_ARPA_INET_H
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
#ifdef HAVE_UTSNAME_H
|
||||
#include <sys/utsname.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
@@ -865,7 +862,7 @@ static CURLcode ftp_state_cwd(struct Curl_easy *data,
|
||||
if(conn->bits.reuse && ftpc->entrypath &&
|
||||
/* no need to go to entrypath when we have an absolute path */
|
||||
!(ftpc->dirdepth && ftpc->dirs[0][0] == '/')) {
|
||||
/* This is a re-used connection. Since we change directory to where the
|
||||
/* This is a reused connection. Since we change directory to where the
|
||||
transfer is taking place, we must first get back to the original dir
|
||||
where we ended up after login: */
|
||||
ftpc->cwdcount = 0; /* we count this as the first path, then we add one
|
||||
@@ -975,7 +972,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
|
||||
if(ip_end) {
|
||||
/* either ipv6 or (ipv4|domain|interface):port(-range) */
|
||||
#ifdef ENABLE_IPV6
|
||||
if(Curl_inet_pton(AF_INET6, string_ftpport, sa6) == 1) {
|
||||
if(Curl_inet_pton(AF_INET6, string_ftpport, &sa6->sin6_addr) == 1) {
|
||||
/* ipv6 */
|
||||
port_min = port_max = 0;
|
||||
strcpy(addr, string_ftpport);
|
||||
@@ -1900,7 +1897,7 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data,
|
||||
if(data->set.ftp_skip_ip) {
|
||||
/* told to ignore the remotely given IP but instead use the host we used
|
||||
for the control connection */
|
||||
infof(data, "Skip %u.%u.%u.%u for data connection, re-use %s instead",
|
||||
infof(data, "Skip %u.%u.%u.%u for data connection, reuse %s instead",
|
||||
ip[0], ip[1], ip[2], ip[3],
|
||||
conn->host.name);
|
||||
ftpc->newhost = strdup(control_address(conn));
|
||||
|
||||
@@ -185,7 +185,7 @@ static CURLcode gopher_do(struct Curl_easy *data, bool *done)
|
||||
if(strlen(sel) < 1)
|
||||
break;
|
||||
|
||||
result = Curl_write(data, sockfd, sel, k, &amount);
|
||||
result = Curl_nwrite(data, FIRSTSOCKET, sel, k, &amount);
|
||||
if(!result) { /* Which may not have written it all! */
|
||||
result = Curl_client_write(data, CLIENTWRITE_HEADER, sel, amount);
|
||||
if(result)
|
||||
@@ -227,7 +227,7 @@ static CURLcode gopher_do(struct Curl_easy *data, bool *done)
|
||||
free(sel_org);
|
||||
|
||||
if(!result)
|
||||
result = Curl_write(data, sockfd, "\r\n", 2, &amount);
|
||||
result = Curl_nwrite(data, FIRSTSOCKET, "\r\n", 2, &amount);
|
||||
if(result) {
|
||||
failf(data, "Failed sending Gopher request");
|
||||
return result;
|
||||
|
||||
@@ -300,9 +300,16 @@ CURLcode Curl_headers_push(struct Curl_easy *data, const char *header,
|
||||
if(data->state.prevhead)
|
||||
/* line folding, append value to the previous header's value */
|
||||
return unfold_value(data, header, hlen);
|
||||
else
|
||||
/* can't unfold without a previous header */
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
else {
|
||||
/* Can't unfold without a previous header. Instead of erroring, just
|
||||
pass the leading blanks. */
|
||||
while(hlen && ISBLANK(*header)) {
|
||||
header++;
|
||||
hlen--;
|
||||
}
|
||||
if(!hlen)
|
||||
return CURLE_WEIRD_SERVER_REPLY;
|
||||
}
|
||||
}
|
||||
|
||||
hs = calloc(1, sizeof(*hs) + hlen);
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||
#if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI)) \
|
||||
|| !defined(CURL_DISABLE_AWS)
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
@@ -169,4 +170,4 @@ CURLcode Curl_hmacit(const struct HMAC_params *hashparams,
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
#endif /* CURL_DISABLE_CRYPTO_AUTH */
|
||||
#endif /* Using NTLM (without SSPI) or AWS */
|
||||
|
||||
@@ -121,19 +121,6 @@
|
||||
|
||||
static void freednsentry(void *freethis);
|
||||
|
||||
/*
|
||||
* Return # of addresses in a Curl_addrinfo struct
|
||||
*/
|
||||
static int num_addresses(const struct Curl_addrinfo *addr)
|
||||
{
|
||||
int i = 0;
|
||||
while(addr) {
|
||||
addr = addr->ai_next;
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_printable_address() stores a printable version of the 1st address
|
||||
* given in the 'ai' argument. The result will be stored in the buf that is
|
||||
@@ -388,6 +375,19 @@ Curl_fetch_addr(struct Curl_easy *data,
|
||||
}
|
||||
|
||||
#ifndef CURL_DISABLE_SHUFFLE_DNS
|
||||
/*
|
||||
* Return # of addresses in a Curl_addrinfo struct
|
||||
*/
|
||||
static int num_addresses(const struct Curl_addrinfo *addr)
|
||||
{
|
||||
int i = 0;
|
||||
while(addr) {
|
||||
addr = addr->ai_next;
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data,
|
||||
struct Curl_addrinfo **addr);
|
||||
/*
|
||||
@@ -601,7 +601,7 @@ bool Curl_ipv6works(struct Curl_easy *data)
|
||||
if(data) {
|
||||
/* the nature of most system is that IPv6 status doesn't come and go
|
||||
during a program's lifetime so we only probe the first time and then we
|
||||
have the info kept for fast re-use */
|
||||
have the info kept for fast reuse */
|
||||
DEBUGASSERT(data);
|
||||
DEBUGASSERT(data->multi);
|
||||
if(data->multi->ipv6_up == IPV6_UNKNOWN) {
|
||||
@@ -1240,7 +1240,7 @@ err:
|
||||
dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
|
||||
|
||||
if(dns) {
|
||||
infof(data, "RESOLVE %.*s:%d is - old addresses discarded",
|
||||
infof(data, "RESOLVE %.*s:%d - old addresses discarded",
|
||||
(int)hlen, host_begin, port);
|
||||
/* delete old entry, there are two reasons for this
|
||||
1. old entry may have different addresses.
|
||||
|
||||
+133
-43
@@ -233,7 +233,6 @@ static CURLcode http_setup_conn(struct Curl_easy *data,
|
||||
if(!http)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
Curl_mime_initpart(&http->form);
|
||||
data->req.p.http = http;
|
||||
connkeep(conn, "HTTP default");
|
||||
|
||||
@@ -342,6 +341,8 @@ char *Curl_copy_header_value(const char *header)
|
||||
}
|
||||
|
||||
#ifndef CURL_DISABLE_HTTP_AUTH
|
||||
|
||||
#ifndef CURL_DISABLE_BASIC_AUTH
|
||||
/*
|
||||
* http_output_basic() sets up an Authorization: header (or the proxy version)
|
||||
* for HTTP Basic authentication.
|
||||
@@ -403,6 +404,9 @@ fail:
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef CURL_DISABLE_BEARER_AUTH
|
||||
/*
|
||||
* http_output_bearer() sets up an Authorization: header
|
||||
* for HTTP Bearer authentication.
|
||||
@@ -430,6 +434,8 @@ fail:
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* pickoneauth() selects the most favourable authentication method from the
|
||||
* ones available and the ones we want.
|
||||
*
|
||||
@@ -446,18 +452,26 @@ static bool pickoneauth(struct auth *pick, unsigned long mask)
|
||||
of preference in case of the existence of multiple accepted types. */
|
||||
if(avail & CURLAUTH_NEGOTIATE)
|
||||
pick->picked = CURLAUTH_NEGOTIATE;
|
||||
#ifndef CURL_DISABLE_BEARER_AUTH
|
||||
else if(avail & CURLAUTH_BEARER)
|
||||
pick->picked = CURLAUTH_BEARER;
|
||||
#endif
|
||||
#ifndef CURL_DISABLE_DIGEST_AUTH
|
||||
else if(avail & CURLAUTH_DIGEST)
|
||||
pick->picked = CURLAUTH_DIGEST;
|
||||
#endif
|
||||
else if(avail & CURLAUTH_NTLM)
|
||||
pick->picked = CURLAUTH_NTLM;
|
||||
else if(avail & CURLAUTH_NTLM_WB)
|
||||
pick->picked = CURLAUTH_NTLM_WB;
|
||||
#ifndef CURL_DISABLE_BASIC_AUTH
|
||||
else if(avail & CURLAUTH_BASIC)
|
||||
pick->picked = CURLAUTH_BASIC;
|
||||
#endif
|
||||
#ifndef CURL_DISABLE_AWS
|
||||
else if(avail & CURLAUTH_AWS_SIGV4)
|
||||
pick->picked = CURLAUTH_AWS_SIGV4;
|
||||
#endif
|
||||
else {
|
||||
pick->picked = CURLAUTH_PICKNONE; /* we select to use nothing */
|
||||
picked = FALSE;
|
||||
@@ -723,11 +737,11 @@ output_auth_headers(struct Curl_easy *data,
|
||||
CURLcode result = CURLE_OK;
|
||||
(void)conn;
|
||||
|
||||
#ifdef CURL_DISABLE_CRYPTO_AUTH
|
||||
#ifdef CURL_DISABLE_DIGEST_AUTH
|
||||
(void)request;
|
||||
(void)path;
|
||||
#endif
|
||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||
#ifndef CURL_DISABLE_AWS
|
||||
if(authstatus->picked == CURLAUTH_AWS_SIGV4) {
|
||||
auth = "AWS_SIGV4";
|
||||
result = Curl_output_aws_sigv4(data, proxy);
|
||||
@@ -763,7 +777,7 @@ output_auth_headers(struct Curl_easy *data,
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||
#ifndef CURL_DISABLE_DIGEST_AUTH
|
||||
if(authstatus->picked == CURLAUTH_DIGEST) {
|
||||
auth = "Digest";
|
||||
result = Curl_output_digest(data,
|
||||
@@ -775,6 +789,7 @@ output_auth_headers(struct Curl_easy *data,
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifndef CURL_DISABLE_BASIC_AUTH
|
||||
if(authstatus->picked == CURLAUTH_BASIC) {
|
||||
/* Basic */
|
||||
if(
|
||||
@@ -794,6 +809,8 @@ output_auth_headers(struct Curl_easy *data,
|
||||
functions work that way */
|
||||
authstatus->done = TRUE;
|
||||
}
|
||||
#endif
|
||||
#ifndef CURL_DISABLE_BEARER_AUTH
|
||||
if(authstatus->picked == CURLAUTH_BEARER) {
|
||||
/* Bearer */
|
||||
if((!proxy && data->set.str[STRING_BEARER] &&
|
||||
@@ -808,6 +825,7 @@ output_auth_headers(struct Curl_easy *data,
|
||||
functions work that way */
|
||||
authstatus->done = TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(auth) {
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
@@ -866,7 +884,12 @@ Curl_http_output_auth(struct Curl_easy *data,
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
(conn->bits.httpproxy && conn->bits.proxy_user_passwd) ||
|
||||
#endif
|
||||
data->state.aptr.user || data->set.str[STRING_BEARER])
|
||||
data->state.aptr.user ||
|
||||
#ifdef USE_SPNEGO
|
||||
authhost->want & CURLAUTH_NEGOTIATE ||
|
||||
authproxy->want & CURLAUTH_NEGOTIATE ||
|
||||
#endif
|
||||
data->set.str[STRING_BEARER])
|
||||
/* continue please */;
|
||||
else {
|
||||
authhost->done = TRUE;
|
||||
@@ -1064,7 +1087,7 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||
#ifndef CURL_DISABLE_DIGEST_AUTH
|
||||
if(checkprefix("Digest", auth) && is_valid_auth_separator(auth[6])) {
|
||||
if((authp->avail & CURLAUTH_DIGEST) != 0)
|
||||
infof(data, "Ignoring duplicate digest auth header.");
|
||||
@@ -1087,6 +1110,7 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifndef CURL_DISABLE_BASIC_AUTH
|
||||
if(checkprefix("Basic", auth) &&
|
||||
is_valid_auth_separator(auth[5])) {
|
||||
*availp |= CURLAUTH_BASIC;
|
||||
@@ -1101,6 +1125,8 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifndef CURL_DISABLE_BEARER_AUTH
|
||||
if(checkprefix("Bearer", auth) &&
|
||||
is_valid_auth_separator(auth[6])) {
|
||||
*availp |= CURLAUTH_BEARER;
|
||||
@@ -1113,6 +1139,7 @@ CURLcode Curl_http_input_auth(struct Curl_easy *data, bool proxy,
|
||||
data->state.authproblem = TRUE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* there may be multiple methods on one line, so keep reading */
|
||||
while(*auth && *auth != ',') /* read up to the next comma */
|
||||
@@ -1277,7 +1304,7 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
|
||||
curl_off_t *bytes_written,
|
||||
/* how much of the buffer contains body data */
|
||||
curl_off_t included_body_bytes,
|
||||
int socketindex)
|
||||
int sockindex)
|
||||
{
|
||||
ssize_t amount;
|
||||
CURLcode result;
|
||||
@@ -1285,12 +1312,9 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
|
||||
size_t size;
|
||||
struct connectdata *conn = data->conn;
|
||||
size_t sendsize;
|
||||
curl_socket_t sockfd;
|
||||
size_t headersize;
|
||||
|
||||
DEBUGASSERT(socketindex <= SECONDARYSOCKET);
|
||||
|
||||
sockfd = Curl_conn_get_socket(data, socketindex);
|
||||
DEBUGASSERT(sockindex <= SECONDARYSOCKET && sockindex >= 0);
|
||||
|
||||
/* The looping below is required since we use non-blocking sockets, but due
|
||||
to the circumstances we will just loop and try again and again etc */
|
||||
@@ -1372,9 +1396,25 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
|
||||
else
|
||||
sendsize = size;
|
||||
}
|
||||
|
||||
/* We currently cannot send more that this for http here:
|
||||
* - if sending blocks, it return 0 as amount
|
||||
* - we then whisk aside the `in` into the `http` struct
|
||||
* and install our own `data->state.fread_func` that
|
||||
* on subsequent calls reads `in` empty.
|
||||
* - when the whisked away `in` is empty, the `fread_func`
|
||||
* is restored ot its original state.
|
||||
* The problem is that `fread_func` can only return
|
||||
* `upload_buffer_size` lengths. If the send we do here
|
||||
* is larger and blocks, we do re-sending with smaller
|
||||
* amounts of data and connection filters do not like
|
||||
* that.
|
||||
*/
|
||||
if(http && (sendsize > (size_t)data->set.upload_buffer_size))
|
||||
sendsize = (size_t)data->set.upload_buffer_size;
|
||||
}
|
||||
|
||||
result = Curl_write(data, sockfd, ptr, sendsize, &amount);
|
||||
result = Curl_nwrite(data, sockindex, ptr, sendsize, &amount);
|
||||
|
||||
if(!result) {
|
||||
/*
|
||||
@@ -1527,7 +1567,7 @@ CURLcode Curl_http_connect(struct Curl_easy *data, bool *done)
|
||||
struct connectdata *conn = data->conn;
|
||||
|
||||
/* We default to persistent connections. We set this already in this connect
|
||||
function to make the re-use checks properly be able to check this bit. */
|
||||
function to make the reuse checks properly be able to check this bit. */
|
||||
connkeep(conn, "HTTP default");
|
||||
|
||||
return Curl_conn_connect(data, FIRSTSOCKET, FALSE, done);
|
||||
@@ -1572,7 +1612,6 @@ CURLcode Curl_http_done(struct Curl_easy *data,
|
||||
return CURLE_OK;
|
||||
|
||||
Curl_dyn_free(&http->send_buffer);
|
||||
Curl_mime_cleanpart(&http->form);
|
||||
Curl_dyn_reset(&data->state.headerb);
|
||||
Curl_hyper_done(data);
|
||||
Curl_ws_done(data);
|
||||
@@ -2370,45 +2409,53 @@ CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn,
|
||||
|
||||
switch(httpreq) {
|
||||
case HTTPREQ_POST_MIME:
|
||||
http->sendit = &data->set.mimepost;
|
||||
data->state.mimepost = &data->set.mimepost;
|
||||
break;
|
||||
#ifndef CURL_DISABLE_FORM_API
|
||||
case HTTPREQ_POST_FORM:
|
||||
/* Convert the form structure into a mime structure. */
|
||||
Curl_mime_cleanpart(&http->form);
|
||||
result = Curl_getformdata(data, &http->form, data->set.httppost,
|
||||
data->state.fread_func);
|
||||
if(result)
|
||||
return result;
|
||||
http->sendit = &http->form;
|
||||
/* Convert the form structure into a mime structure, then keep
|
||||
the conversion */
|
||||
if(!data->state.formp) {
|
||||
data->state.formp = calloc(sizeof(curl_mimepart), 1);
|
||||
if(!data->state.formp)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
Curl_mime_cleanpart(data->state.formp);
|
||||
result = Curl_getformdata(data, data->state.formp, data->set.httppost,
|
||||
data->state.fread_func);
|
||||
if(result)
|
||||
return result;
|
||||
data->state.mimepost = data->state.formp;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
http->sendit = NULL;
|
||||
data->state.mimepost = NULL;
|
||||
}
|
||||
|
||||
#ifndef CURL_DISABLE_MIME
|
||||
if(http->sendit) {
|
||||
if(data->state.mimepost) {
|
||||
const char *cthdr = Curl_checkheaders(data, STRCONST("Content-Type"));
|
||||
|
||||
/* Read and seek body only. */
|
||||
http->sendit->flags |= MIME_BODY_ONLY;
|
||||
data->state.mimepost->flags |= MIME_BODY_ONLY;
|
||||
|
||||
/* Prepare the mime structure headers & set content type. */
|
||||
|
||||
if(cthdr)
|
||||
for(cthdr += 13; *cthdr == ' '; cthdr++)
|
||||
;
|
||||
else if(http->sendit->kind == MIMEKIND_MULTIPART)
|
||||
else if(data->state.mimepost->kind == MIMEKIND_MULTIPART)
|
||||
cthdr = "multipart/form-data";
|
||||
|
||||
curl_mime_headers(http->sendit, data->set.headers, 0);
|
||||
result = Curl_mime_prepare_headers(data, http->sendit, cthdr,
|
||||
curl_mime_headers(data->state.mimepost, data->set.headers, 0);
|
||||
result = Curl_mime_prepare_headers(data, data->state.mimepost, cthdr,
|
||||
NULL, MIMESTRATEGY_FORM);
|
||||
curl_mime_headers(http->sendit, NULL, 0);
|
||||
curl_mime_headers(data->state.mimepost, NULL, 0);
|
||||
if(!result)
|
||||
result = Curl_mime_rewind(http->sendit);
|
||||
result = Curl_mime_rewind(data->state.mimepost);
|
||||
if(result)
|
||||
return result;
|
||||
http->postsize = Curl_mime_size(http->sendit);
|
||||
http->postsize = Curl_mime_size(data->state.mimepost);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2564,7 +2611,7 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
|
||||
{
|
||||
struct curl_slist *hdr;
|
||||
|
||||
for(hdr = http->sendit->curlheaders; hdr; hdr = hdr->next) {
|
||||
for(hdr = data->state.mimepost->curlheaders; hdr; hdr = hdr->next) {
|
||||
result = Curl_dyn_addf(r, "%s\r\n", hdr->data);
|
||||
if(result)
|
||||
return result;
|
||||
@@ -2599,7 +2646,7 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
|
||||
|
||||
/* Read from mime structure. */
|
||||
data->state.fread_func = (curl_read_callback) Curl_mime_read;
|
||||
data->state.in = (void *) http->sendit;
|
||||
data->state.in = (void *) data->state.mimepost;
|
||||
http->sending = HTTPSEND_BODY;
|
||||
|
||||
/* this sends the buffer and frees all the buffer resources */
|
||||
@@ -2683,7 +2730,7 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
|
||||
|
||||
if(!data->req.upload_chunky) {
|
||||
/* We're not sending it 'chunked', append it to the request
|
||||
already now to reduce the number if send() calls */
|
||||
already now to reduce the number of send() calls */
|
||||
result = Curl_dyn_addn(r, data->set.postfields,
|
||||
(size_t)http->postsize);
|
||||
included_body = http->postsize;
|
||||
@@ -3024,7 +3071,7 @@ CURLcode Curl_http_firstwrite(struct Curl_easy *data,
|
||||
*done = TRUE;
|
||||
return CURLE_OK;
|
||||
}
|
||||
/* We have a new url to load, but since we want to be able to re-use this
|
||||
/* We have a new url to load, but since we want to be able to reuse this
|
||||
connection properly, we read the full response in "ignore more" */
|
||||
k->ignorebody = TRUE;
|
||||
infof(data, "Ignoring the response-body");
|
||||
@@ -3064,7 +3111,7 @@ CURLcode Curl_http_firstwrite(struct Curl_easy *data,
|
||||
data->info.httpcode = 304;
|
||||
infof(data, "Simulate an HTTP 304 response");
|
||||
/* we abort the transfer before it is completed == we ruin the
|
||||
re-use ability. Close the connection */
|
||||
reuse ability. Close the connection */
|
||||
streamclose(conn, "Simulated 304 handling");
|
||||
return CURLE_OK;
|
||||
}
|
||||
@@ -3308,8 +3355,8 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
|
||||
altused ? altused : ""
|
||||
);
|
||||
|
||||
/* clear userpwd and proxyuserpwd to avoid re-using old credentials
|
||||
* from re-used connections */
|
||||
/* clear userpwd and proxyuserpwd to avoid reusing old credentials
|
||||
* from reused connections */
|
||||
Curl_safefree(data->state.aptr.userpwd);
|
||||
Curl_safefree(data->state.aptr.proxyuserpwd);
|
||||
free(altused);
|
||||
@@ -3918,6 +3965,29 @@ static CURLcode verify_header(struct Curl_easy *data)
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
CURLcode Curl_bump_headersize(struct Curl_easy *data,
|
||||
size_t delta,
|
||||
bool connect_only)
|
||||
{
|
||||
size_t bad = 0;
|
||||
if(delta < MAX_HTTP_RESP_HEADER_SIZE) {
|
||||
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)
|
||||
bad = data->info.header_size;
|
||||
}
|
||||
else
|
||||
bad = data->info.header_size + delta;
|
||||
if(bad) {
|
||||
failf(data, "Too large response headers: %zu > %u",
|
||||
bad, MAX_HTTP_RESP_HEADER_SIZE);
|
||||
return CURLE_RECV_ERROR;
|
||||
}
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read any HTTP header lines from the server and pass them to the client app.
|
||||
*/
|
||||
@@ -4056,6 +4126,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
||||
/* Switching Protocols */
|
||||
if(k->upgr101 == UPGR101_H2) {
|
||||
/* Switching to HTTP/2 */
|
||||
DEBUGASSERT(conn->httpversion < 20);
|
||||
infof(data, "Received 101, Switching to HTTP/2");
|
||||
k->upgr101 = UPGR101_RECEIVED;
|
||||
|
||||
@@ -4098,6 +4169,11 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(k->upgr101 == UPGR101_H2) {
|
||||
/* A requested upgrade was denied, poke the multi handle to possibly
|
||||
allow a pending pipewait to continue */
|
||||
Curl_multi_connchanged(data->multi);
|
||||
}
|
||||
k->header = FALSE; /* no more header to parse! */
|
||||
|
||||
if((k->size == -1) && !k->chunk && !conn->bits.close &&
|
||||
@@ -4165,8 +4241,9 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
data->info.header_size += (long)headerlen;
|
||||
data->req.headerbytecount += (long)headerlen;
|
||||
result = Curl_bump_headersize(data, headerlen, FALSE);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
/*
|
||||
* When all the headers have been parsed, see if we should give
|
||||
@@ -4229,7 +4306,18 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
||||
if((k->httpcode == 417) && data->state.expect100header) {
|
||||
/* 417 Expectation Failed - try again without the Expect
|
||||
header */
|
||||
infof(data, "Got 417 while waiting for a 100");
|
||||
if(!k->writebytecount &&
|
||||
k->exp100 == EXP100_AWAITING_CONTINUE) {
|
||||
infof(data, "Got HTTP failure 417 while waiting for a 100");
|
||||
}
|
||||
else {
|
||||
infof(data, "Got HTTP failure 417 while sending data");
|
||||
streamclose(conn,
|
||||
"Stop sending data before everything sent");
|
||||
result = http_perhapsrewind(data, conn);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
data->state.disableexpect = TRUE;
|
||||
DEBUGASSERT(!data->req.newurl);
|
||||
data->req.newurl = strdup(data->state.url);
|
||||
@@ -4488,8 +4576,10 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
data->info.header_size += Curl_dyn_len(&data->state.headerb);
|
||||
data->req.headerbytecount += Curl_dyn_len(&data->state.headerb);
|
||||
result = Curl_bump_headersize(data, Curl_dyn_len(&data->state.headerb),
|
||||
FALSE);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
Curl_dyn_reset(&data->state.headerb);
|
||||
}
|
||||
|
||||
@@ -64,6 +64,10 @@ extern const struct Curl_handler Curl_handler_wss;
|
||||
|
||||
struct dynhds;
|
||||
|
||||
CURLcode Curl_bump_headersize(struct Curl_easy *data,
|
||||
size_t delta,
|
||||
bool connect_only);
|
||||
|
||||
/* Header specific functions */
|
||||
bool Curl_compareheader(const char *headerline, /* line to check */
|
||||
const char *header, /* header keyword _with_ colon */
|
||||
@@ -183,21 +187,19 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data);
|
||||
#define EXPECT_100_THRESHOLD (1024*1024)
|
||||
#endif
|
||||
|
||||
/* MAX_HTTP_RESP_HEADER_SIZE is the maximum size of all response headers
|
||||
combined that libcurl allows for a single HTTP response, any HTTP
|
||||
version. This count includes CONNECT response headers. */
|
||||
#define MAX_HTTP_RESP_HEADER_SIZE (300*1024)
|
||||
|
||||
#endif /* CURL_DISABLE_HTTP */
|
||||
|
||||
/****************************************************************************
|
||||
* HTTP unique setup
|
||||
***************************************************************************/
|
||||
struct HTTP {
|
||||
curl_mimepart *sendit;
|
||||
curl_off_t postsize; /* off_t to handle large file sizes */
|
||||
const char *postdata;
|
||||
|
||||
const char *p_pragma; /* Pragma: string */
|
||||
|
||||
/* For FORM posting */
|
||||
curl_mimepart form;
|
||||
|
||||
struct back {
|
||||
curl_read_callback fread_func; /* backup storage for fread pointer */
|
||||
void *fread_in; /* backup storage for fread_in pointer */
|
||||
@@ -292,7 +294,7 @@ void Curl_http_req_free(struct httpreq *req);
|
||||
|
||||
/**
|
||||
* Create the list of HTTP/2 headers which represent the request,
|
||||
* using HTTP/2 pseudo headers preceeding the `req->headers`.
|
||||
* using HTTP/2 pseudo headers preceding the `req->headers`.
|
||||
*
|
||||
* Applies the following transformations:
|
||||
* - if `authority` is set, any "Host" header is removed.
|
||||
|
||||
@@ -163,7 +163,7 @@ static CURLcode start_req(struct h1_req_parser *parser,
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* no SPACE found or empty TARGET or empy HTTP_VERSION */
|
||||
/* no SPACE found or empty TARGET or empty HTTP_VERSION */
|
||||
if(!target_len || !hv_len)
|
||||
goto out;
|
||||
|
||||
|
||||
+363
-235
File diff suppressed because it is too large
Load Diff
@@ -24,7 +24,7 @@
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
|
||||
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_AWS)
|
||||
|
||||
#include "urldata.h"
|
||||
#include "strcase.h"
|
||||
@@ -44,16 +44,16 @@
|
||||
|
||||
#include "slist.h"
|
||||
|
||||
#define HMAC_SHA256(k, kl, d, dl, o) \
|
||||
do { \
|
||||
ret = Curl_hmacit(Curl_HMAC_SHA256, \
|
||||
(unsigned char *)k, \
|
||||
kl, \
|
||||
(unsigned char *)d, \
|
||||
dl, o); \
|
||||
if(ret) { \
|
||||
goto fail; \
|
||||
} \
|
||||
#define HMAC_SHA256(k, kl, d, dl, o) \
|
||||
do { \
|
||||
result = Curl_hmacit(Curl_HMAC_SHA256, \
|
||||
(unsigned char *)k, \
|
||||
kl, \
|
||||
(unsigned char *)d, \
|
||||
dl, o); \
|
||||
if(result) { \
|
||||
goto fail; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define TIMESTAMP_SIZE 17
|
||||
@@ -199,10 +199,41 @@ static CURLcode make_headers(struct Curl_easy *data,
|
||||
head = tmp_head;
|
||||
}
|
||||
|
||||
/* copy user headers to our header list. the logic is based on how http.c
|
||||
handles user headers.
|
||||
|
||||
user headers in format 'name:' with no value are used to signal that an
|
||||
internal header of that name should be removed. those user headers are not
|
||||
added to this list.
|
||||
|
||||
user headers in format 'name;' with no value are used to signal that a
|
||||
header of that name with no value should be sent. those user headers are
|
||||
added to this list but in the format that they will be sent, ie the
|
||||
semi-colon is changed to a colon for format 'name:'.
|
||||
|
||||
user headers with a value of whitespace only, or without a colon or
|
||||
semi-colon, are not added to this list.
|
||||
*/
|
||||
for(l = data->set.headers; l; l = l->next) {
|
||||
tmp_head = curl_slist_append(head, l->data);
|
||||
if(!tmp_head)
|
||||
char *dupdata, *ptr;
|
||||
char *sep = strchr(l->data, ':');
|
||||
if(!sep)
|
||||
sep = strchr(l->data, ';');
|
||||
if(!sep || (*sep == ':' && !*(sep + 1)))
|
||||
continue;
|
||||
for(ptr = sep + 1; ISSPACE(*ptr); ++ptr)
|
||||
;
|
||||
if(!*ptr && ptr != sep + 1) /* a value of whitespace only */
|
||||
continue;
|
||||
dupdata = strdup(l->data);
|
||||
if(!dupdata)
|
||||
goto fail;
|
||||
dupdata[sep - l->data] = ':';
|
||||
tmp_head = Curl_slist_append_nodup(head, dupdata);
|
||||
if(!tmp_head) {
|
||||
free(dupdata);
|
||||
goto fail;
|
||||
}
|
||||
head = tmp_head;
|
||||
}
|
||||
|
||||
@@ -214,23 +245,22 @@ static CURLcode make_headers(struct Curl_easy *data,
|
||||
if(!tmp_head)
|
||||
goto fail;
|
||||
head = tmp_head;
|
||||
*date_header = curl_maprintf("%s: %s", date_hdr_key, timestamp);
|
||||
*date_header = curl_maprintf("%s: %s\r\n", date_hdr_key, timestamp);
|
||||
}
|
||||
else {
|
||||
char *value;
|
||||
|
||||
*date_header = strdup(*date_header);
|
||||
if(!*date_header)
|
||||
goto fail;
|
||||
|
||||
value = strchr(*date_header, ':');
|
||||
if(!value)
|
||||
if(!value) {
|
||||
*date_header = NULL;
|
||||
goto fail;
|
||||
}
|
||||
++value;
|
||||
while(ISBLANK(*value))
|
||||
++value;
|
||||
strncpy(timestamp, value, TIMESTAMP_SIZE - 1);
|
||||
timestamp[TIMESTAMP_SIZE - 1] = 0;
|
||||
*date_header = NULL;
|
||||
}
|
||||
|
||||
/* alpha-sort in a case sensitive manner */
|
||||
@@ -370,9 +400,112 @@ fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct pair {
|
||||
const char *p;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
static int compare_func(const void *a, const void *b)
|
||||
{
|
||||
const struct pair *aa = a;
|
||||
const struct pair *bb = b;
|
||||
return strncmp(aa->p, bb->p, aa->len < bb->len ? aa->len : bb->len);
|
||||
}
|
||||
|
||||
#define MAX_QUERYPAIRS 64
|
||||
|
||||
static CURLcode canon_query(struct Curl_easy *data,
|
||||
const char *query, struct dynbuf *dq)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
int entry = 0;
|
||||
int i;
|
||||
const char *p = query;
|
||||
struct pair array[MAX_QUERYPAIRS];
|
||||
struct pair *ap = &array[0];
|
||||
if(!query)
|
||||
return result;
|
||||
|
||||
/* sort the name=value pairs first */
|
||||
do {
|
||||
char *amp;
|
||||
entry++;
|
||||
ap->p = p;
|
||||
amp = strchr(p, '&');
|
||||
if(amp)
|
||||
ap->len = amp - p; /* excluding the ampersand */
|
||||
else {
|
||||
ap->len = strlen(p);
|
||||
break;
|
||||
}
|
||||
ap++;
|
||||
p = amp + 1;
|
||||
} while(entry < MAX_QUERYPAIRS);
|
||||
if(entry == MAX_QUERYPAIRS) {
|
||||
/* too many query pairs for us */
|
||||
failf(data, "aws-sigv4: too many query pairs in URL");
|
||||
return CURLE_URL_MALFORMAT;
|
||||
}
|
||||
|
||||
qsort(&array[0], entry, sizeof(struct pair), compare_func);
|
||||
|
||||
ap = &array[0];
|
||||
for(i = 0; !result && (i < entry); i++, ap++) {
|
||||
size_t len;
|
||||
const char *q = ap->p;
|
||||
if(!ap->len)
|
||||
continue;
|
||||
for(len = ap->len; len && !result; q++, len--) {
|
||||
if(ISALNUM(*q))
|
||||
result = Curl_dyn_addn(dq, q, 1);
|
||||
else {
|
||||
switch(*q) {
|
||||
case '-':
|
||||
case '.':
|
||||
case '_':
|
||||
case '~':
|
||||
case '=':
|
||||
/* allowed as-is */
|
||||
result = Curl_dyn_addn(dq, q, 1);
|
||||
break;
|
||||
case '%':
|
||||
/* uppercase the following if hexadecimal */
|
||||
if(ISXDIGIT(q[1]) && ISXDIGIT(q[2])) {
|
||||
char tmp[3]="%";
|
||||
tmp[1] = Curl_raw_toupper(q[1]);
|
||||
tmp[2] = Curl_raw_toupper(q[2]);
|
||||
result = Curl_dyn_addn(dq, tmp, 3);
|
||||
q += 2;
|
||||
len -= 2;
|
||||
}
|
||||
else
|
||||
/* '%' without a following two-digit hex, encode it */
|
||||
result = Curl_dyn_addn(dq, "%25", 3);
|
||||
break;
|
||||
default: {
|
||||
/* URL encode */
|
||||
const char hex[] = "0123456789ABCDEF";
|
||||
char out[3]={'%'};
|
||||
out[1] = hex[((unsigned char)*q)>>4];
|
||||
out[2] = hex[*q & 0xf];
|
||||
result = Curl_dyn_addn(dq, out, 3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(i < entry - 1) {
|
||||
/* insert ampersands between query pairs */
|
||||
result = Curl_dyn_addn(dq, "&", 1);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
|
||||
{
|
||||
CURLcode ret = CURLE_OUT_OF_MEMORY;
|
||||
CURLcode result = CURLE_OUT_OF_MEMORY;
|
||||
struct connectdata *conn = data->conn;
|
||||
size_t len;
|
||||
const char *arg;
|
||||
@@ -388,6 +521,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
|
||||
char date[9];
|
||||
struct dynbuf canonical_headers;
|
||||
struct dynbuf signed_headers;
|
||||
struct dynbuf canonical_query;
|
||||
char *date_header = NULL;
|
||||
Curl_HttpReq httpreq;
|
||||
const char *method = NULL;
|
||||
@@ -416,6 +550,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
|
||||
|
||||
/* we init those buffers here, so goto fail will free initialized dynbuf */
|
||||
Curl_dyn_init(&canonical_headers, CURL_MAX_HTTP_HEADER);
|
||||
Curl_dyn_init(&canonical_query, CURL_MAX_HTTP_HEADER);
|
||||
Curl_dyn_init(&signed_headers, CURL_MAX_HTTP_HEADER);
|
||||
|
||||
/*
|
||||
@@ -431,15 +566,15 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
|
||||
/* provider1[:provider2[:region[:service]]]
|
||||
|
||||
No string can be longer than N bytes of non-whitespace
|
||||
*/
|
||||
*/
|
||||
(void)sscanf(arg, "%" MAX_SIGV4_LEN_TXT "[^:]"
|
||||
":%" MAX_SIGV4_LEN_TXT "[^:]"
|
||||
":%" MAX_SIGV4_LEN_TXT "[^:]"
|
||||
":%" MAX_SIGV4_LEN_TXT "s",
|
||||
provider0, provider1, region, service);
|
||||
if(!provider0[0]) {
|
||||
failf(data, "first provider can't be empty");
|
||||
ret = CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
failf(data, "first aws-sigv4 provider can't be empty");
|
||||
result = CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
goto fail;
|
||||
}
|
||||
else if(!provider1[0])
|
||||
@@ -448,35 +583,38 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
|
||||
if(!service[0]) {
|
||||
char *hostdot = strchr(hostname, '.');
|
||||
if(!hostdot) {
|
||||
failf(data, "service missing in parameters and hostname");
|
||||
ret = CURLE_URL_MALFORMAT;
|
||||
failf(data, "aws-sigv4: service missing in parameters and hostname");
|
||||
result = CURLE_URL_MALFORMAT;
|
||||
goto fail;
|
||||
}
|
||||
len = hostdot - hostname;
|
||||
if(len > MAX_SIGV4_LEN) {
|
||||
failf(data, "service too long in hostname");
|
||||
ret = CURLE_URL_MALFORMAT;
|
||||
failf(data, "aws-sigv4: service too long in hostname");
|
||||
result = CURLE_URL_MALFORMAT;
|
||||
goto fail;
|
||||
}
|
||||
strncpy(service, hostname, len);
|
||||
service[len] = '\0';
|
||||
|
||||
infof(data, "aws_sigv4: picked service %s from host", service);
|
||||
|
||||
if(!region[0]) {
|
||||
const char *reg = hostdot + 1;
|
||||
const char *hostreg = strchr(reg, '.');
|
||||
if(!hostreg) {
|
||||
failf(data, "region missing in parameters and hostname");
|
||||
ret = CURLE_URL_MALFORMAT;
|
||||
failf(data, "aws-sigv4: region missing in parameters and hostname");
|
||||
result = CURLE_URL_MALFORMAT;
|
||||
goto fail;
|
||||
}
|
||||
len = hostreg - reg;
|
||||
if(len > MAX_SIGV4_LEN) {
|
||||
failf(data, "region too long in hostname");
|
||||
ret = CURLE_URL_MALFORMAT;
|
||||
failf(data, "aws-sigv4: region too long in hostname");
|
||||
result = CURLE_URL_MALFORMAT;
|
||||
goto fail;
|
||||
}
|
||||
strncpy(region, reg, len);
|
||||
region[len] = '\0';
|
||||
infof(data, "aws_sigv4: picked region %s from host", region);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -491,11 +629,11 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
|
||||
|
||||
if(!payload_hash) {
|
||||
if(sign_as_s3)
|
||||
ret = calc_s3_payload_hash(data, httpreq, provider1, sha_hash,
|
||||
sha_hex, content_sha256_hdr);
|
||||
result = calc_s3_payload_hash(data, httpreq, provider1, sha_hash,
|
||||
sha_hex, content_sha256_hdr);
|
||||
else
|
||||
ret = calc_payload_hash(data, sha_hash, sha_hex);
|
||||
if(ret)
|
||||
result = calc_payload_hash(data, sha_hash, sha_hex);
|
||||
if(result)
|
||||
goto fail;
|
||||
|
||||
payload_hash = sha_hex;
|
||||
@@ -514,21 +652,20 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
|
||||
#else
|
||||
time(&clock);
|
||||
#endif
|
||||
ret = Curl_gmtime(clock, &tm);
|
||||
if(ret) {
|
||||
result = Curl_gmtime(clock, &tm);
|
||||
if(result) {
|
||||
goto fail;
|
||||
}
|
||||
if(!strftime(timestamp, sizeof(timestamp), "%Y%m%dT%H%M%SZ", &tm)) {
|
||||
ret = CURLE_OUT_OF_MEMORY;
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = make_headers(data, hostname, timestamp, provider1,
|
||||
&date_header, content_sha256_hdr,
|
||||
&canonical_headers, &signed_headers);
|
||||
if(ret)
|
||||
result = make_headers(data, hostname, timestamp, provider1,
|
||||
&date_header, content_sha256_hdr,
|
||||
&canonical_headers, &signed_headers);
|
||||
if(result)
|
||||
goto fail;
|
||||
ret = CURLE_OUT_OF_MEMORY;
|
||||
|
||||
if(*content_sha256_hdr) {
|
||||
/* make_headers() needed this without the \r\n for canonicalization */
|
||||
@@ -540,6 +677,11 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
|
||||
memcpy(date, timestamp, sizeof(date));
|
||||
date[sizeof(date) - 1] = 0;
|
||||
|
||||
result = canon_query(data, data->state.up.query, &canonical_query);
|
||||
if(result)
|
||||
goto fail;
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
|
||||
canonical_request =
|
||||
curl_maprintf("%s\n" /* HTTPRequestMethod */
|
||||
"%s\n" /* CanonicalURI */
|
||||
@@ -549,13 +691,16 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
|
||||
"%.*s", /* HashedRequestPayload in hex */
|
||||
method,
|
||||
data->state.up.path,
|
||||
data->state.up.query ? data->state.up.query : "",
|
||||
Curl_dyn_ptr(&canonical_query) ?
|
||||
Curl_dyn_ptr(&canonical_query) : "",
|
||||
Curl_dyn_ptr(&canonical_headers),
|
||||
Curl_dyn_ptr(&signed_headers),
|
||||
(int)payload_hash_len, payload_hash);
|
||||
if(!canonical_request)
|
||||
goto fail;
|
||||
|
||||
DEBUGF(infof(data, "Canonical request: %s", canonical_request));
|
||||
|
||||
/* provider 0 lowercase */
|
||||
Curl_strntolower(provider0, provider0, strlen(provider0));
|
||||
request_type = curl_maprintf("%s4_request", provider0);
|
||||
@@ -612,14 +757,19 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
|
||||
"Credential=%s/%s, "
|
||||
"SignedHeaders=%s, "
|
||||
"Signature=%s\r\n"
|
||||
"%s\r\n"
|
||||
/*
|
||||
* date_header is added here, only if it wasn't
|
||||
* user-specified (using CURLOPT_HTTPHEADER).
|
||||
* date_header includes \r\n
|
||||
*/
|
||||
"%s"
|
||||
"%s", /* optional sha256 header includes \r\n */
|
||||
provider0,
|
||||
user,
|
||||
credential_scope,
|
||||
Curl_dyn_ptr(&signed_headers),
|
||||
sha_hex,
|
||||
date_header,
|
||||
date_header ? date_header : "",
|
||||
content_sha256_hdr);
|
||||
if(!auth_headers) {
|
||||
goto fail;
|
||||
@@ -628,9 +778,10 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
|
||||
Curl_safefree(data->state.aptr.userpwd);
|
||||
data->state.aptr.userpwd = auth_headers;
|
||||
data->state.authhost.done = TRUE;
|
||||
ret = CURLE_OK;
|
||||
result = CURLE_OK;
|
||||
|
||||
fail:
|
||||
Curl_dyn_free(&canonical_query);
|
||||
Curl_dyn_free(&canonical_headers);
|
||||
Curl_dyn_free(&signed_headers);
|
||||
free(canonical_request);
|
||||
@@ -639,7 +790,7 @@ fail:
|
||||
free(str_to_sign);
|
||||
free(secret);
|
||||
free(date_header);
|
||||
return ret;
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /* !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH) */
|
||||
#endif /* !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_AWS) */
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
|
||||
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_DIGEST_AUTH)
|
||||
|
||||
#include "urldata.h"
|
||||
#include "strcase.h"
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
***************************************************************************/
|
||||
#include "curl_setup.h"
|
||||
|
||||
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
|
||||
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_DIGEST_AUTH)
|
||||
|
||||
/* this is for digest header input */
|
||||
CURLcode Curl_input_digest(struct Curl_easy *data,
|
||||
@@ -39,6 +39,6 @@ CURLcode Curl_output_digest(struct Curl_easy *data,
|
||||
|
||||
void Curl_http_auth_cleanup_digest(struct Curl_easy *data);
|
||||
|
||||
#endif /* !CURL_DISABLE_HTTP && !CURL_DISABLE_CRYPTO_AUTH */
|
||||
#endif /* !CURL_DISABLE_HTTP && !CURL_DISABLE_DIGEST_AUTH */
|
||||
|
||||
#endif /* HEADER_CURL_HTTP_DIGEST_H */
|
||||
|
||||
@@ -69,7 +69,7 @@ static CURLcode http_proxy_cf_connect(struct Curl_cfilter *cf,
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
DEBUGF(LOG_CF(data, cf, "connect"));
|
||||
CURL_TRC_CF(data, cf, "connect");
|
||||
connect_sub:
|
||||
result = cf->next->cft->do_connect(cf->next, data, blocking, done);
|
||||
if(result || !*done)
|
||||
@@ -86,7 +86,7 @@ connect_sub:
|
||||
case CURL_HTTP_VERSION_NONE:
|
||||
case CURL_HTTP_VERSION_1_0:
|
||||
case CURL_HTTP_VERSION_1_1:
|
||||
DEBUGF(LOG_CF(data, cf, "installing subfilter for HTTP/1.1"));
|
||||
CURL_TRC_CF(data, cf, "installing subfilter for HTTP/1.1");
|
||||
infof(data, "CONNECT tunnel: HTTP/1.%d negotiated",
|
||||
(alpn == CURL_HTTP_VERSION_1_0)? 0 : 1);
|
||||
result = Curl_cf_h1_proxy_insert_after(cf, data);
|
||||
@@ -96,7 +96,7 @@ connect_sub:
|
||||
break;
|
||||
#ifdef USE_NGHTTP2
|
||||
case CURL_HTTP_VERSION_2:
|
||||
DEBUGF(LOG_CF(data, cf, "installing subfilter for HTTP/2"));
|
||||
CURL_TRC_CF(data, cf, "installing subfilter for HTTP/2");
|
||||
infof(data, "CONNECT tunnel: HTTP/2 negotiated");
|
||||
result = Curl_cf_h2_proxy_insert_after(cf, data);
|
||||
if(result)
|
||||
@@ -105,7 +105,7 @@ connect_sub:
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
DEBUGF(LOG_CF(data, cf, "installing subfilter for default HTTP/1.1"));
|
||||
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;
|
||||
@@ -156,7 +156,7 @@ static void http_proxy_cf_destroy(struct Curl_cfilter *cf,
|
||||
struct cf_proxy_ctx *ctx = cf->ctx;
|
||||
|
||||
(void)data;
|
||||
DEBUGF(LOG_CF(data, cf, "destroy"));
|
||||
CURL_TRC_CF(data, cf, "destroy");
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
@@ -165,7 +165,7 @@ static void http_proxy_cf_close(struct Curl_cfilter *cf,
|
||||
{
|
||||
struct cf_proxy_ctx *ctx = cf->ctx;
|
||||
|
||||
DEBUGF(LOG_CF(data, cf, "close"));
|
||||
CURL_TRC_CF(data, cf, "close");
|
||||
cf->connected = FALSE;
|
||||
if(ctx->cf_protocol) {
|
||||
struct Curl_cfilter *f;
|
||||
|
||||
+100
-20
@@ -68,27 +68,59 @@ WINBASEAPI int WINAPI IdnToUnicode(DWORD dwFlags,
|
||||
|
||||
#define IDN_MAX_LENGTH 255
|
||||
|
||||
bool Curl_win32_idn_to_ascii(const char *in, char **out)
|
||||
static CURLcode win32_idn_to_ascii(const char *in, char **out)
|
||||
{
|
||||
bool success = FALSE;
|
||||
|
||||
wchar_t *in_w = curlx_convert_UTF8_to_wchar(in);
|
||||
*out = NULL;
|
||||
if(in_w) {
|
||||
wchar_t punycode[IDN_MAX_LENGTH];
|
||||
int chars = IdnToAscii(0, in_w, -1, punycode, IDN_MAX_LENGTH);
|
||||
int chars = IdnToAscii(0, in_w, (int)(wcslen(in_w) + 1), punycode,
|
||||
IDN_MAX_LENGTH);
|
||||
curlx_unicodefree(in_w);
|
||||
if(chars) {
|
||||
char *mstr = curlx_convert_wchar_to_UTF8(punycode);
|
||||
if(mstr) {
|
||||
*out = strdup(mstr);
|
||||
curlx_unicodefree(mstr);
|
||||
if(*out)
|
||||
success = TRUE;
|
||||
if(!*out)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
else
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
else
|
||||
return CURLE_URL_MALFORMAT;
|
||||
}
|
||||
|
||||
return success;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static CURLcode win32_ascii_to_idn(const char *in, char **output)
|
||||
{
|
||||
char *out = NULL;
|
||||
|
||||
wchar_t *in_w = curlx_convert_UTF8_to_wchar(in);
|
||||
if(in_w) {
|
||||
WCHAR idn[IDN_MAX_LENGTH]; /* stores a UTF-16 string */
|
||||
int chars = IdnToUnicode(0, in_w, (int)(wcslen(in_w) + 1), idn,
|
||||
IDN_MAX_LENGTH);
|
||||
if(chars) {
|
||||
/* 'chars' is "the number of characters retrieved" */
|
||||
char *mstr = curlx_convert_wchar_to_UTF8(idn);
|
||||
if(mstr) {
|
||||
out = strdup(mstr);
|
||||
curlx_unicodefree(mstr);
|
||||
if(!out)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
else
|
||||
return CURLE_URL_MALFORMAT;
|
||||
}
|
||||
else
|
||||
return CURLE_URL_MALFORMAT;
|
||||
*output = out;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
#endif /* USE_WIN32_IDN */
|
||||
@@ -115,10 +147,15 @@ bool Curl_is_ASCII_name(const char *hostname)
|
||||
/*
|
||||
* Curl_idn_decode() returns an allocated IDN decoded string if it was
|
||||
* possible. NULL on error.
|
||||
*
|
||||
* CURLE_URL_MALFORMAT - the host name could not be converted
|
||||
* CURLE_OUT_OF_MEMORY - memory problem
|
||||
*
|
||||
*/
|
||||
static char *idn_decode(const char *input)
|
||||
static CURLcode idn_decode(const char *input, char **output)
|
||||
{
|
||||
char *decoded = NULL;
|
||||
CURLcode result = CURLE_OK;
|
||||
#ifdef USE_LIBIDN2
|
||||
if(idn2_check_version(IDN2_VERSION)) {
|
||||
int flags = IDN2_NFC_INPUT
|
||||
@@ -135,26 +172,68 @@ static char *idn_decode(const char *input)
|
||||
compatibility */
|
||||
rc = IDN2_LOOKUP(input, &decoded, IDN2_TRANSITIONAL);
|
||||
if(rc != IDN2_OK)
|
||||
decoded = NULL;
|
||||
result = CURLE_URL_MALFORMAT;
|
||||
}
|
||||
#elif defined(USE_WIN32_IDN)
|
||||
if(!Curl_win32_idn_to_ascii(input, &decoded))
|
||||
decoded = NULL;
|
||||
result = win32_idn_to_ascii(input, &decoded);
|
||||
#endif
|
||||
return decoded;
|
||||
if(!result)
|
||||
*output = decoded;
|
||||
return result;
|
||||
}
|
||||
|
||||
char *Curl_idn_decode(const char *input)
|
||||
static CURLcode idn_encode(const char *puny, char **output)
|
||||
{
|
||||
char *d = idn_decode(input);
|
||||
char *enc = NULL;
|
||||
#ifdef USE_LIBIDN2
|
||||
if(d) {
|
||||
int rc = idn2_to_unicode_8z8z(puny, &enc, 0);
|
||||
if(rc != IDNA_SUCCESS)
|
||||
return rc == IDNA_MALLOC_ERROR ? CURLE_OUT_OF_MEMORY : CURLE_URL_MALFORMAT;
|
||||
#elif defined(USE_WIN32_IDN)
|
||||
CURLcode result = win32_ascii_to_idn(puny, &enc);
|
||||
if(result)
|
||||
return result;
|
||||
#endif
|
||||
*output = enc;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
CURLcode Curl_idn_decode(const char *input, char **output)
|
||||
{
|
||||
char *d = NULL;
|
||||
CURLcode result = idn_decode(input, &d);
|
||||
#ifdef USE_LIBIDN2
|
||||
if(!result) {
|
||||
char *c = strdup(d);
|
||||
idn2_free(d);
|
||||
d = c;
|
||||
if(c)
|
||||
d = c;
|
||||
else
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
#endif
|
||||
return d;
|
||||
if(!result)
|
||||
*output = d;
|
||||
return result;
|
||||
}
|
||||
|
||||
CURLcode Curl_idn_encode(const char *puny, char **output)
|
||||
{
|
||||
char *d = NULL;
|
||||
CURLcode result = idn_encode(puny, &d);
|
||||
#ifdef USE_LIBIDN2
|
||||
if(!result) {
|
||||
char *c = strdup(d);
|
||||
idn2_free(d);
|
||||
if(c)
|
||||
d = c;
|
||||
else
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
#endif
|
||||
if(!result)
|
||||
*output = d;
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -182,8 +261,9 @@ CURLcode Curl_idnconvert_hostname(struct hostname *host)
|
||||
#ifdef USE_IDN
|
||||
/* Check name for non-ASCII and convert hostname if we can */
|
||||
if(!Curl_is_ASCII_name(host->name)) {
|
||||
char *decoded = idn_decode(host->name);
|
||||
if(decoded) {
|
||||
char *decoded;
|
||||
CURLcode result = idn_decode(host->name, &decoded);
|
||||
if(!result) {
|
||||
if(!*decoded) {
|
||||
/* zero length is a bad host name */
|
||||
Curl_idn_free(decoded);
|
||||
@@ -195,7 +275,7 @@ CURLcode Curl_idnconvert_hostname(struct hostname *host)
|
||||
host->name = host->encalloc;
|
||||
}
|
||||
else
|
||||
return CURLE_URL_MALFORMAT;
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
return CURLE_OK;
|
||||
|
||||
@@ -24,15 +24,13 @@
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef USE_WIN32_IDN
|
||||
bool Curl_win32_idn_to_ascii(const char *in, char **out);
|
||||
#endif /* USE_WIN32_IDN */
|
||||
bool Curl_is_ASCII_name(const char *hostname);
|
||||
CURLcode Curl_idnconvert_hostname(struct hostname *host);
|
||||
#if defined(USE_LIBIDN2) || defined(USE_WIN32_IDN)
|
||||
#define USE_IDN
|
||||
void Curl_free_idnconverted_hostname(struct hostname *host);
|
||||
char *Curl_idn_decode(const char *input);
|
||||
CURLcode Curl_idn_decode(const char *input, char **output);
|
||||
CURLcode Curl_idn_encode(const char *input, char **output);
|
||||
#ifdef USE_LIBIDN2
|
||||
#define Curl_idn_free(x) idn2_free(x)
|
||||
#else
|
||||
|
||||
@@ -92,6 +92,8 @@ unsigned int Curl_ipv6_scope(const struct sockaddr *sa)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef CURL_DISABLE_BINDLOCAL
|
||||
|
||||
#if defined(HAVE_GETIFADDRS)
|
||||
|
||||
if2ip_result_t Curl_if2ip(int af,
|
||||
@@ -254,3 +256,5 @@ if2ip_result_t Curl_if2ip(int af,
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* CURL_DISABLE_BINDLOCAL */
|
||||
|
||||
+35
-68
@@ -45,9 +45,6 @@
|
||||
#ifdef HAVE_ARPA_INET_H
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
#ifdef HAVE_UTSNAME_H
|
||||
#include <sys/utsname.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
@@ -1094,10 +1091,19 @@ static CURLcode imap_state_select_resp(struct Curl_easy *data, int imapcode,
|
||||
|
||||
if(imapcode == '*') {
|
||||
/* See if this is an UIDVALIDITY response */
|
||||
char tmp[20];
|
||||
if(sscanf(line + 2, "OK [UIDVALIDITY %19[0123456789]]", tmp) == 1) {
|
||||
Curl_safefree(imapc->mailbox_uidvalidity);
|
||||
imapc->mailbox_uidvalidity = strdup(tmp);
|
||||
if(checkprefix("OK [UIDVALIDITY ", line + 2)) {
|
||||
size_t len = 0;
|
||||
const char *p = &line[2] + strlen("OK [UIDVALIDITY ");
|
||||
while((len < 20) && p[len] && ISDIGIT(p[len]))
|
||||
len++;
|
||||
if(len && (p[len] == ']')) {
|
||||
struct dynbuf uid;
|
||||
Curl_dyn_init(&uid, 20);
|
||||
if(Curl_dyn_addn(&uid, p, len))
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
Curl_safefree(imapc->mailbox_uidvalidity);
|
||||
imapc->mailbox_uidvalidity = Curl_dyn_ptr(&uid);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(imapcode == IMAP_RESP_OK) {
|
||||
@@ -1109,7 +1115,10 @@ static CURLcode imap_state_select_resp(struct Curl_easy *data, int imapcode,
|
||||
}
|
||||
else {
|
||||
/* Note the currently opened mailbox on this connection */
|
||||
DEBUGASSERT(!imapc->mailbox);
|
||||
imapc->mailbox = strdup(imap->mailbox);
|
||||
if(!imapc->mailbox)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
if(imap->custom)
|
||||
result = imap_perform_list(data);
|
||||
@@ -1806,79 +1815,37 @@ static CURLcode imap_sendf(struct Curl_easy *data, const char *fmt, ...)
|
||||
*/
|
||||
static char *imap_atom(const char *str, bool escape_only)
|
||||
{
|
||||
/* !checksrc! disable PARENBRACE 1 */
|
||||
const char atom_specials[] = "(){ %*]";
|
||||
const char *p1;
|
||||
char *p2;
|
||||
size_t backsp_count = 0;
|
||||
size_t quote_count = 0;
|
||||
bool others_exists = FALSE;
|
||||
size_t newlen = 0;
|
||||
char *newstr = NULL;
|
||||
struct dynbuf line;
|
||||
size_t nclean;
|
||||
size_t len;
|
||||
|
||||
if(!str)
|
||||
return NULL;
|
||||
|
||||
/* Look for "atom-specials", counting the backslash and quote characters as
|
||||
these will need escaping */
|
||||
p1 = str;
|
||||
while(*p1) {
|
||||
if(*p1 == '\\')
|
||||
backsp_count++;
|
||||
else if(*p1 == '"')
|
||||
quote_count++;
|
||||
else if(!escape_only) {
|
||||
const char *p3 = atom_specials;
|
||||
|
||||
while(*p3 && !others_exists) {
|
||||
if(*p1 == *p3)
|
||||
others_exists = TRUE;
|
||||
|
||||
p3++;
|
||||
}
|
||||
}
|
||||
|
||||
p1++;
|
||||
}
|
||||
|
||||
/* Does the input contain any "atom-special" characters? */
|
||||
if(!backsp_count && !quote_count && !others_exists)
|
||||
len = strlen(str);
|
||||
nclean = strcspn(str, "() {%*]\\\"");
|
||||
if(len == nclean)
|
||||
/* nothing to escape, return a strdup */
|
||||
return strdup(str);
|
||||
|
||||
/* Calculate the new string length */
|
||||
newlen = strlen(str) + backsp_count + quote_count + (escape_only ? 0 : 2);
|
||||
Curl_dyn_init(&line, 2000);
|
||||
|
||||
/* Allocate the new string */
|
||||
newstr = (char *) malloc((newlen + 1) * sizeof(char));
|
||||
if(!newstr)
|
||||
if(!escape_only && Curl_dyn_addn(&line, "\"", 1))
|
||||
return NULL;
|
||||
|
||||
/* Surround the string in quotes if necessary */
|
||||
p2 = newstr;
|
||||
if(!escape_only) {
|
||||
newstr[0] = '"';
|
||||
newstr[newlen - 1] = '"';
|
||||
p2++;
|
||||
while(*str) {
|
||||
if((*str == '\\' || *str == '"') &&
|
||||
Curl_dyn_addn(&line, "\\", 1))
|
||||
return NULL;
|
||||
if(Curl_dyn_addn(&line, str, 1))
|
||||
return NULL;
|
||||
str++;
|
||||
}
|
||||
|
||||
/* Copy the string, escaping backslash and quote characters along the way */
|
||||
p1 = str;
|
||||
while(*p1) {
|
||||
if(*p1 == '\\' || *p1 == '"') {
|
||||
*p2 = '\\';
|
||||
p2++;
|
||||
}
|
||||
if(!escape_only && Curl_dyn_addn(&line, "\"", 1))
|
||||
return NULL;
|
||||
|
||||
*p2 = *p1;
|
||||
|
||||
p1++;
|
||||
p2++;
|
||||
}
|
||||
|
||||
/* Terminate the string */
|
||||
newstr[newlen] = '\0';
|
||||
|
||||
return newstr;
|
||||
return Curl_dyn_ptr(&line);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
||||
@@ -117,8 +117,9 @@ static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size)
|
||||
|
||||
for(i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
|
||||
if(words[i] == 0) {
|
||||
if(cur.base == -1)
|
||||
cur.base = i, cur.len = 1;
|
||||
if(cur.base == -1) {
|
||||
cur.base = i; cur.len = 1;
|
||||
}
|
||||
else
|
||||
cur.len++;
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ static CURLcode ftpsend(struct Curl_easy *data, struct connectdata *conn,
|
||||
char *sptr = s;
|
||||
CURLcode result = CURLE_OK;
|
||||
#ifdef HAVE_GSSAPI
|
||||
enum protection_level data_sec = conn->data_prot;
|
||||
unsigned char data_sec = conn->data_prot;
|
||||
#endif
|
||||
|
||||
if(!cmd)
|
||||
@@ -91,7 +91,7 @@ static CURLcode ftpsend(struct Curl_easy *data, struct connectdata *conn,
|
||||
#ifdef HAVE_GSSAPI
|
||||
conn->data_prot = PROT_CMD;
|
||||
#endif
|
||||
result = Curl_write(data, conn->sock[FIRSTSOCKET], sptr, write_len,
|
||||
result = Curl_nwrite(data, FIRSTSOCKET, sptr, write_len,
|
||||
&bytes_written);
|
||||
#ifdef HAVE_GSSAPI
|
||||
DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST);
|
||||
@@ -385,7 +385,7 @@ static const struct Curl_sec_client_mech Curl_krb5_client_mech = {
|
||||
};
|
||||
|
||||
static const struct {
|
||||
enum protection_level level;
|
||||
unsigned char level;
|
||||
const char *name;
|
||||
} level_names[] = {
|
||||
{ PROT_CLEAR, "clear" },
|
||||
@@ -394,8 +394,7 @@ static const struct {
|
||||
{ PROT_PRIVATE, "private" }
|
||||
};
|
||||
|
||||
static enum protection_level
|
||||
name_to_level(const char *name)
|
||||
static unsigned char name_to_level(const char *name)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < (int)sizeof(level_names)/(int)sizeof(level_names[0]); i++)
|
||||
@@ -734,7 +733,7 @@ static int sec_set_protection_level(struct Curl_easy *data)
|
||||
{
|
||||
int code;
|
||||
struct connectdata *conn = data->conn;
|
||||
enum protection_level level = conn->request_data_prot;
|
||||
unsigned char level = conn->request_data_prot;
|
||||
|
||||
DEBUGASSERT(level > PROT_NONE && level < PROT_LAST);
|
||||
|
||||
@@ -793,7 +792,7 @@ static int sec_set_protection_level(struct Curl_easy *data)
|
||||
int
|
||||
Curl_sec_request_prot(struct connectdata *conn, const char *level)
|
||||
{
|
||||
enum protection_level l = name_to_level(level);
|
||||
unsigned char l = name_to_level(level);
|
||||
if(l == PROT_NONE)
|
||||
return -1;
|
||||
DEBUGASSERT(l > PROT_NONE && l < PROT_LAST);
|
||||
|
||||
@@ -239,7 +239,7 @@ static int ldap_win_bind_auth(LDAP *server, const char *user,
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#if !defined(CURL_DISABLE_CRYPTO_AUTH)
|
||||
#if !defined(CURL_DISABLE_DIGEST_AUTH)
|
||||
if(authflags & CURLAUTH_DIGEST) {
|
||||
method = LDAP_AUTH_DIGEST;
|
||||
}
|
||||
@@ -762,7 +762,7 @@ quit:
|
||||
|
||||
/* no data to transfer */
|
||||
Curl_setup_transfer(data, -1, -1, FALSE, -1);
|
||||
connclose(conn, "LDAP connection always disable re-use");
|
||||
connclose(conn, "LDAP connection always disable reuse");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -24,21 +24,16 @@
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#if defined(__APPLE__)
|
||||
|
||||
#if !defined(TARGET_OS_OSX) || TARGET_OS_OSX
|
||||
#ifdef CURL_MACOS_CALL_COPYPROXIES
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "macos.h"
|
||||
|
||||
#if defined(ENABLE_IPV6) && defined(CURL_OSX_CALL_COPYPROXIES)
|
||||
#include <SystemConfiguration/SCDynamicStoreCopySpecific.h>
|
||||
#endif
|
||||
|
||||
CURLcode Curl_macos_init(void)
|
||||
{
|
||||
#if defined(ENABLE_IPV6) && defined(CURL_OSX_CALL_COPYPROXIES)
|
||||
{
|
||||
/*
|
||||
* The automagic conversion from IPv4 literals to IPv6 literals only
|
||||
@@ -46,17 +41,15 @@ CURLcode Curl_macos_init(void)
|
||||
* first. As Curl currently doesn't support system-wide HTTP proxies, we
|
||||
* therefore don't use any value this function might return.
|
||||
*
|
||||
* This function is only available on a macOS and is not needed for
|
||||
* IPv4-only builds, hence the conditions above.
|
||||
* This function is only available on macOS and is not needed for
|
||||
* IPv4-only builds, hence the conditions for defining
|
||||
* CURL_MACOS_CALL_COPYPROXIES in curl_setup.h.
|
||||
*/
|
||||
CFDictionaryRef dict = SCDynamicStoreCopyProxies(NULL);
|
||||
if(dict)
|
||||
CFRelease(dict);
|
||||
}
|
||||
#endif
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
#endif /* TARGET_OS_OSX */
|
||||
|
||||
#endif /* __APPLE__ */
|
||||
#endif
|
||||
|
||||
@@ -23,9 +23,10 @@
|
||||
* SPDX-License-Identifier: curl
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#if defined(__APPLE__) && (!defined(TARGET_OS_OSX) || TARGET_OS_OSX)
|
||||
#ifdef CURL_MACOS_CALL_COPYPROXIES
|
||||
|
||||
CURLcode Curl_macos_init(void);
|
||||
|
||||
|
||||
+30
-12
@@ -42,6 +42,7 @@
|
||||
|
||||
#ifdef USE_WOLFSSL
|
||||
#include <wolfssl/options.h>
|
||||
#define VOID_MD4_INIT
|
||||
#ifdef NO_MD4
|
||||
#define WOLFSSL_NO_MD4
|
||||
#endif
|
||||
@@ -92,9 +93,10 @@
|
||||
|
||||
typedef struct md4_ctx MD4_CTX;
|
||||
|
||||
static void MD4_Init(MD4_CTX *ctx)
|
||||
static int MD4_Init(MD4_CTX *ctx)
|
||||
{
|
||||
md4_init(ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
|
||||
@@ -114,9 +116,9 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
|
||||
#elif defined(AN_APPLE_OS)
|
||||
typedef CC_MD4_CTX MD4_CTX;
|
||||
|
||||
static void MD4_Init(MD4_CTX *ctx)
|
||||
static int MD4_Init(MD4_CTX *ctx)
|
||||
{
|
||||
(void)CC_MD4_Init(ctx);
|
||||
return CC_MD4_Init(ctx);
|
||||
}
|
||||
|
||||
static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
|
||||
@@ -137,15 +139,22 @@ struct md4_ctx {
|
||||
};
|
||||
typedef struct md4_ctx MD4_CTX;
|
||||
|
||||
static void MD4_Init(MD4_CTX *ctx)
|
||||
static int MD4_Init(MD4_CTX *ctx)
|
||||
{
|
||||
ctx->hCryptProv = 0;
|
||||
ctx->hHash = 0;
|
||||
|
||||
if(CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, PROV_RSA_FULL,
|
||||
CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
|
||||
CryptCreateHash(ctx->hCryptProv, CALG_MD4, 0, 0, &ctx->hHash);
|
||||
if(!CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, PROV_RSA_FULL,
|
||||
CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
|
||||
return 0;
|
||||
|
||||
if(!CryptCreateHash(ctx->hCryptProv, CALG_MD4, 0, 0, &ctx->hHash)) {
|
||||
CryptReleaseContext(ctx->hCryptProv, 0);
|
||||
ctx->hCryptProv = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
|
||||
@@ -176,10 +185,11 @@ struct md4_ctx {
|
||||
};
|
||||
typedef struct md4_ctx MD4_CTX;
|
||||
|
||||
static void MD4_Init(MD4_CTX *ctx)
|
||||
static int MD4_Init(MD4_CTX *ctx)
|
||||
{
|
||||
ctx->data = NULL;
|
||||
ctx->size = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
|
||||
@@ -258,7 +268,7 @@ struct md4_ctx {
|
||||
};
|
||||
typedef struct md4_ctx MD4_CTX;
|
||||
|
||||
static void MD4_Init(MD4_CTX *ctx);
|
||||
static int MD4_Init(MD4_CTX *ctx);
|
||||
static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size);
|
||||
static void MD4_Final(unsigned char *result, MD4_CTX *ctx);
|
||||
|
||||
@@ -397,7 +407,7 @@ static const void *body(MD4_CTX *ctx, const void *data, unsigned long size)
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static void MD4_Init(MD4_CTX *ctx)
|
||||
static int MD4_Init(MD4_CTX *ctx)
|
||||
{
|
||||
ctx->a = 0x67452301;
|
||||
ctx->b = 0xefcdab89;
|
||||
@@ -406,6 +416,7 @@ static void MD4_Init(MD4_CTX *ctx)
|
||||
|
||||
ctx->lo = 0;
|
||||
ctx->hi = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
|
||||
@@ -496,14 +507,21 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
|
||||
|
||||
#endif /* CRYPTO LIBS */
|
||||
|
||||
void Curl_md4it(unsigned char *output, const unsigned char *input,
|
||||
const size_t len)
|
||||
CURLcode Curl_md4it(unsigned char *output, const unsigned char *input,
|
||||
const size_t len)
|
||||
{
|
||||
MD4_CTX ctx;
|
||||
|
||||
#ifdef VOID_MD4_INIT
|
||||
MD4_Init(&ctx);
|
||||
#else
|
||||
if(!MD4_Init(&ctx))
|
||||
return CURLE_FAILED_INIT;
|
||||
#endif
|
||||
|
||||
MD4_Update(&ctx, input, curlx_uztoui(len));
|
||||
MD4_Final(output, &ctx);
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
#endif /* USE_CURL_NTLM_CORE */
|
||||
|
||||
@@ -24,7 +24,8 @@
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||
#if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI)) \
|
||||
|| !defined(CURL_DISABLE_DIGEST_AUTH)
|
||||
|
||||
#include <string.h>
|
||||
#include <curl/curl.h>
|
||||
@@ -213,7 +214,8 @@ static CURLcode my_md5_init(my_md5_ctx *ctx)
|
||||
|
||||
if(!CryptCreateHash(ctx->hCryptProv, CALG_MD5, 0, 0, &ctx->hHash)) {
|
||||
CryptReleaseContext(ctx->hCryptProv, 0);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
ctx->hCryptProv = 0;
|
||||
return CURLE_FAILED_INIT;
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
@@ -651,4 +653,4 @@ CURLcode Curl_MD5_final(struct MD5_context *context, unsigned char *result)
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
#endif /* CURL_DISABLE_CRYPTO_AUTH */
|
||||
#endif /* Using NTLM (without SSPI) || Digest */
|
||||
|
||||
@@ -1167,14 +1167,16 @@ static void mime_subparts_unbind(void *ptr)
|
||||
|
||||
void Curl_mime_cleanpart(curl_mimepart *part)
|
||||
{
|
||||
cleanup_part_content(part);
|
||||
curl_slist_free_all(part->curlheaders);
|
||||
if(part->flags & MIME_USERHEADERS_OWNER)
|
||||
curl_slist_free_all(part->userheaders);
|
||||
Curl_safefree(part->mimetype);
|
||||
Curl_safefree(part->name);
|
||||
Curl_safefree(part->filename);
|
||||
Curl_mime_initpart(part);
|
||||
if(part) {
|
||||
cleanup_part_content(part);
|
||||
curl_slist_free_all(part->curlheaders);
|
||||
if(part->flags & MIME_USERHEADERS_OWNER)
|
||||
curl_slist_free_all(part->userheaders);
|
||||
Curl_safefree(part->mimetype);
|
||||
Curl_safefree(part->name);
|
||||
Curl_safefree(part->filename);
|
||||
Curl_mime_initpart(part);
|
||||
}
|
||||
}
|
||||
|
||||
/* Recursively delete a mime handle and its parts. */
|
||||
|
||||
@@ -117,11 +117,9 @@ static CURLcode mqtt_send(struct Curl_easy *data,
|
||||
char *buf, size_t len)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct connectdata *conn = data->conn;
|
||||
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
|
||||
struct MQTT *mq = data->req.p.mqtt;
|
||||
ssize_t n;
|
||||
result = Curl_write(data, sockfd, buf, len, &n);
|
||||
result = Curl_nwrite(data, FIRSTSOCKET, buf, len, &n);
|
||||
if(result)
|
||||
return result;
|
||||
Curl_debug(data, CURLINFO_HEADER_OUT, buf, (size_t)n);
|
||||
|
||||
@@ -459,7 +459,7 @@ struct Curl_multi *curl_multi_init(void)
|
||||
CURL_DNS_HASH_SIZE);
|
||||
}
|
||||
|
||||
#ifdef DEBUGBUILD
|
||||
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
static void multi_warn_debug(struct Curl_multi *multi, struct Curl_easy *data)
|
||||
{
|
||||
if(!multi->warned) {
|
||||
@@ -638,7 +638,6 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
|
||||
CONNCACHE_UNLOCK(data);
|
||||
|
||||
multi_warn_debug(multi, data);
|
||||
infof(data, "processing: %s", data->state.url);
|
||||
|
||||
return CURLM_OK;
|
||||
}
|
||||
@@ -668,8 +667,14 @@ static CURLcode multi_done(struct Curl_easy *data,
|
||||
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",
|
||||
multi_statename[data->mstate],
|
||||
(int)status, (int)premature, data->state.done));
|
||||
#else
|
||||
DEBUGF(infof(data, "multi_done: status: %d prem: %d done: %d",
|
||||
(int)status, (int)premature, data->state.done));
|
||||
#endif
|
||||
|
||||
if(data->state.done)
|
||||
/* Stop if multi_done() has already been called */
|
||||
@@ -752,7 +757,7 @@ static CURLcode multi_done(struct Curl_easy *data,
|
||||
|
||||
if premature is TRUE, it means this connection was said to be DONE before
|
||||
the entire request operation is complete and thus we can't know in what
|
||||
state it is for re-using, so we're forced to close it. In a perfect world
|
||||
state it is for reusing, so we're forced to close it. In a perfect world
|
||||
we can add code that keep track of if we really must close it here or not,
|
||||
but currently we have no such detail knowledge.
|
||||
*/
|
||||
@@ -769,7 +774,7 @@ static CURLcode multi_done(struct Curl_easy *data,
|
||||
#endif
|
||||
) || conn->bits.close
|
||||
|| (premature && !Curl_conn_is_multiplex(conn, FIRSTSOCKET))) {
|
||||
DEBUGF(infof(data, "multi_done, not re-using connection=%"
|
||||
DEBUGF(infof(data, "multi_done, not reusing connection=%"
|
||||
CURL_FORMAT_CURL_OFF_T ", forbid=%d"
|
||||
", close=%d, premature=%d, conn_multiplex=%d",
|
||||
conn->connection_id,
|
||||
@@ -1105,8 +1110,7 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
|
||||
if(multi->in_callback)
|
||||
return CURLM_RECURSIVE_API_CALL;
|
||||
|
||||
data = multi->easyp;
|
||||
while(data) {
|
||||
for(data = multi->easyp; data; data = data->next) {
|
||||
int bitmap;
|
||||
#ifdef __clang_analyzer_
|
||||
/* to prevent "The left operand of '>=' is a garbage value" warnings */
|
||||
@@ -1115,30 +1119,21 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
|
||||
bitmap = multi_getsock(data, sockbunch);
|
||||
|
||||
for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) {
|
||||
curl_socket_t s = CURL_SOCKET_BAD;
|
||||
|
||||
if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK(sockbunch[i])) {
|
||||
if((bitmap & GETSOCK_MASK_RW(i)) && VALID_SOCK((sockbunch[i]))) {
|
||||
if(!FDSET_SOCK(sockbunch[i]))
|
||||
/* pretend it doesn't exist */
|
||||
continue;
|
||||
FD_SET(sockbunch[i], read_fd_set);
|
||||
s = sockbunch[i];
|
||||
if(bitmap & GETSOCK_READSOCK(i))
|
||||
FD_SET(sockbunch[i], read_fd_set);
|
||||
if(bitmap & GETSOCK_WRITESOCK(i))
|
||||
FD_SET(sockbunch[i], write_fd_set);
|
||||
if((int)sockbunch[i] > this_max_fd)
|
||||
this_max_fd = (int)sockbunch[i];
|
||||
}
|
||||
if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK(sockbunch[i])) {
|
||||
if(!FDSET_SOCK(sockbunch[i]))
|
||||
/* pretend it doesn't exist */
|
||||
continue;
|
||||
FD_SET(sockbunch[i], write_fd_set);
|
||||
s = sockbunch[i];
|
||||
}
|
||||
if(s == CURL_SOCKET_BAD)
|
||||
/* this socket is unused, break out of loop */
|
||||
else {
|
||||
break;
|
||||
if((int)s > this_max_fd)
|
||||
this_max_fd = (int)s;
|
||||
}
|
||||
}
|
||||
|
||||
data = data->next; /* check next handle */
|
||||
}
|
||||
|
||||
*max_fd = this_max_fd;
|
||||
@@ -1201,27 +1196,17 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
|
||||
return CURLM_BAD_FUNCTION_ARGUMENT;
|
||||
|
||||
/* Count up how many fds we have from the multi handle */
|
||||
data = multi->easyp;
|
||||
while(data) {
|
||||
for(data = multi->easyp; data; data = data->next) {
|
||||
bitmap = multi_getsock(data, sockbunch);
|
||||
|
||||
for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) {
|
||||
curl_socket_t s = CURL_SOCKET_BAD;
|
||||
|
||||
if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
|
||||
for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
|
||||
if((bitmap & GETSOCK_MASK_RW(i)) && VALID_SOCK((sockbunch[i]))) {
|
||||
++nfds;
|
||||
s = sockbunch[i];
|
||||
}
|
||||
if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
|
||||
++nfds;
|
||||
s = sockbunch[i];
|
||||
}
|
||||
if(s == CURL_SOCKET_BAD) {
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
data = data->next; /* check next handle */
|
||||
}
|
||||
|
||||
/* If the internally desired timeout is actually shorter than requested from
|
||||
@@ -1261,49 +1246,42 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
|
||||
|
||||
if(curlfds) {
|
||||
/* Add the curl handles to our pollfds first */
|
||||
data = multi->easyp;
|
||||
while(data) {
|
||||
for(data = multi->easyp; data; data = data->next) {
|
||||
bitmap = multi_getsock(data, sockbunch);
|
||||
|
||||
for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
|
||||
curl_socket_t s = CURL_SOCKET_BAD;
|
||||
if((bitmap & GETSOCK_MASK_RW(i)) && VALID_SOCK((sockbunch[i]))) {
|
||||
struct pollfd *ufd = &ufds[nfds++];
|
||||
#ifdef USE_WINSOCK
|
||||
long mask = 0;
|
||||
long mask = 0;
|
||||
#endif
|
||||
if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
|
||||
s = sockbunch[i];
|
||||
ufd->fd = sockbunch[i];
|
||||
ufd->events = 0;
|
||||
if(bitmap & GETSOCK_READSOCK(i)) {
|
||||
#ifdef USE_WINSOCK
|
||||
mask |= FD_READ|FD_ACCEPT|FD_CLOSE;
|
||||
mask |= FD_READ|FD_ACCEPT|FD_CLOSE;
|
||||
#endif
|
||||
ufd->events |= POLLIN;
|
||||
}
|
||||
if(bitmap & GETSOCK_WRITESOCK(i)) {
|
||||
#ifdef USE_WINSOCK
|
||||
mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
|
||||
reset_socket_fdwrite(sockbunch[i]);
|
||||
#endif
|
||||
ufd->events |= POLLOUT;
|
||||
}
|
||||
#ifdef USE_WINSOCK
|
||||
if(WSAEventSelect(sockbunch[i], multi->wsa_event, mask) != 0) {
|
||||
if(ufds_malloc)
|
||||
free(ufds);
|
||||
return CURLM_INTERNAL_ERROR;
|
||||
}
|
||||
#endif
|
||||
ufds[nfds].fd = s;
|
||||
ufds[nfds].events = POLLIN;
|
||||
++nfds;
|
||||
}
|
||||
if((bitmap & GETSOCK_WRITESOCK(i)) && VALID_SOCK((sockbunch[i]))) {
|
||||
s = sockbunch[i];
|
||||
#ifdef USE_WINSOCK
|
||||
mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
|
||||
reset_socket_fdwrite(s);
|
||||
#endif
|
||||
ufds[nfds].fd = s;
|
||||
ufds[nfds].events = POLLOUT;
|
||||
++nfds;
|
||||
}
|
||||
/* s is only set if either being readable or writable is checked */
|
||||
if(s == CURL_SOCKET_BAD) {
|
||||
/* break on entry not checked for being readable or writable */
|
||||
else {
|
||||
break;
|
||||
}
|
||||
#ifdef USE_WINSOCK
|
||||
if(WSAEventSelect(s, multi->wsa_event, mask) != 0) {
|
||||
if(ufds_malloc)
|
||||
free(ufds);
|
||||
return CURLM_INTERNAL_ERROR;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
data = data->next; /* check next handle */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1412,8 +1390,8 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
|
||||
/* Count up all our own sockets that had activity,
|
||||
and remove them from the event. */
|
||||
if(curlfds) {
|
||||
data = multi->easyp;
|
||||
while(data) {
|
||||
|
||||
for(data = multi->easyp; data; data = data->next) {
|
||||
bitmap = multi_getsock(data, sockbunch);
|
||||
|
||||
for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++) {
|
||||
@@ -1430,8 +1408,6 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
data = data->next;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1577,6 +1553,18 @@ static bool multi_ischanged(struct Curl_multi *multi, bool clear)
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_multi_connchanged() is called to tell that there is a connection in
|
||||
* this multi handle that has changed state (multiplexing become possible, the
|
||||
* number of allowed streams changed or similar), and a subsequent use of this
|
||||
* multi handle should move CONNECT_PEND handles back to CONNECT to have them
|
||||
* retry.
|
||||
*/
|
||||
void Curl_multi_connchanged(struct Curl_multi *multi)
|
||||
{
|
||||
multi->recheckstate = TRUE;
|
||||
}
|
||||
|
||||
CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
|
||||
struct Curl_easy *data,
|
||||
struct connectdata *conn)
|
||||
@@ -1611,7 +1599,6 @@ static CURLcode multi_do(struct Curl_easy *data, bool *done)
|
||||
DEBUGASSERT(conn->handler);
|
||||
|
||||
if(conn->handler->do_it)
|
||||
/* generic protocol-specific function pointer set in curl_connect() */
|
||||
result = conn->handler->do_it(data, done);
|
||||
|
||||
return result;
|
||||
@@ -1787,9 +1774,8 @@ static CURLcode protocol_connect(struct Curl_easy *data,
|
||||
*/
|
||||
static CURLcode readrewind(struct Curl_easy *data)
|
||||
{
|
||||
struct connectdata *conn = data->conn;
|
||||
curl_mimepart *mimepart = &data->set.mimepost;
|
||||
DEBUGASSERT(conn);
|
||||
DEBUGASSERT(data->conn);
|
||||
|
||||
data->state.rewindbeforesend = FALSE; /* we rewind now */
|
||||
|
||||
@@ -1802,12 +1788,12 @@ static CURLcode readrewind(struct Curl_easy *data)
|
||||
/* We have sent away data. If not using CURLOPT_POSTFIELDS or
|
||||
CURLOPT_HTTPPOST, call app to rewind
|
||||
*/
|
||||
if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
|
||||
struct HTTP *http = data->req.p.http;
|
||||
|
||||
if(http->sendit)
|
||||
mimepart = http->sendit;
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
if(data->conn->handler->protocol & PROTO_FAMILY_HTTP) {
|
||||
if(data->state.mimepost)
|
||||
mimepart = data->state.mimepost;
|
||||
}
|
||||
#endif
|
||||
if(data->set.postfields ||
|
||||
(data->state.httpreq == HTTPREQ_GET) ||
|
||||
(data->state.httpreq == HTTPREQ_HEAD))
|
||||
@@ -2460,7 +2446,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
|
||||
if(done || (result == CURLE_RECV_ERROR)) {
|
||||
/* If CURLE_RECV_ERROR happens early enough, we assume it was a race
|
||||
* condition and the server closed the re-used connection exactly when
|
||||
* condition and the server closed the reused connection exactly when
|
||||
* we wanted to use it, so figure out if that is indeed the case.
|
||||
*/
|
||||
CURLcode ret = Curl_retry_request(data, &newurl);
|
||||
@@ -2502,7 +2488,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
||||
if(result) {
|
||||
/*
|
||||
* The transfer phase returned error, we mark the connection to get
|
||||
* closed to prevent being re-used. This is because we can't possibly
|
||||
* closed to prevent being reused. This is because we can't possibly
|
||||
* know if the connection is in a good shape or not now. Unless it is
|
||||
* a protocol which uses two "channels" like FTP, as then the error
|
||||
* happened in the data connection.
|
||||
@@ -2933,7 +2919,7 @@ static CURLMcode singlesocket(struct Curl_multi *multi,
|
||||
|
||||
/* walk over the sockets we got right now */
|
||||
for(i = 0; (i< MAX_SOCKSPEREASYHANDLE) &&
|
||||
(curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i)));
|
||||
(curraction & GETSOCK_MASK_RW(i));
|
||||
i++) {
|
||||
unsigned char action = CURL_POLL_NONE;
|
||||
unsigned char prevaction = 0;
|
||||
|
||||
@@ -41,6 +41,8 @@ void Curl_set_in_callback(struct Curl_easy *data, bool value);
|
||||
bool Curl_is_in_callback(struct Curl_easy *easy);
|
||||
CURLcode Curl_preconnect(struct Curl_easy *data);
|
||||
|
||||
void Curl_multi_connchanged(struct Curl_multi *multi);
|
||||
|
||||
/* Internal version of curl_multi_init() accepts size parameters for the
|
||||
socket, connection and dns hashes */
|
||||
struct Curl_multi *Curl_multi_handle(int hashsize, int chashsize,
|
||||
@@ -57,6 +59,9 @@ struct Curl_multi *Curl_multi_handle(int hashsize, int chashsize,
|
||||
/* set the bit for the given sock number to make the bitmap for readable */
|
||||
#define GETSOCK_READSOCK(x) (1 << (x))
|
||||
|
||||
/* 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
|
||||
|
||||
@@ -204,8 +204,7 @@ CURLcode Curl_pp_vsendf(struct Curl_easy *data,
|
||||
#ifdef HAVE_GSSAPI
|
||||
conn->data_prot = PROT_CMD;
|
||||
#endif
|
||||
result = Curl_write(data, conn->sock[FIRSTSOCKET], s, write_len,
|
||||
&bytes_written);
|
||||
result = Curl_nwrite(data, FIRSTSOCKET, s, write_len, &bytes_written);
|
||||
if(result)
|
||||
return result;
|
||||
#ifdef HAVE_GSSAPI
|
||||
@@ -341,7 +340,7 @@ CURLcode Curl_pp_readresp(struct Curl_easy *data,
|
||||
ssize_t clipamount = 0;
|
||||
bool restart = FALSE;
|
||||
|
||||
data->req.headerbytecount += (long)gotbytes;
|
||||
data->req.headerbytecount += (unsigned int)gotbytes;
|
||||
|
||||
pp->nread_resp += gotbytes;
|
||||
for(i = 0; i < gotbytes; ptr++, i++) {
|
||||
@@ -467,11 +466,10 @@ CURLcode Curl_pp_flushsend(struct Curl_easy *data,
|
||||
struct pingpong *pp)
|
||||
{
|
||||
/* we have a piece of a command still left to send */
|
||||
struct connectdata *conn = data->conn;
|
||||
ssize_t written;
|
||||
curl_socket_t sock = conn->sock[FIRSTSOCKET];
|
||||
CURLcode result = Curl_write(data, sock, pp->sendthis + pp->sendsize -
|
||||
pp->sendleft, pp->sendleft, &written);
|
||||
CURLcode result = Curl_nwrite(data, FIRSTSOCKET,
|
||||
pp->sendthis + pp->sendsize - pp->sendleft,
|
||||
pp->sendleft, &written);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
|
||||
@@ -47,9 +47,6 @@
|
||||
#ifdef HAVE_ARPA_INET_H
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
#ifdef HAVE_UTSNAME_H
|
||||
#include <sys/utsname.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
@@ -422,7 +419,7 @@ static CURLcode pop3_perform_user(struct Curl_easy *data,
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||
#ifndef CURL_DISABLE_DIGEST_AUTH
|
||||
/***********************************************************************
|
||||
*
|
||||
* pop3_perform_apop()
|
||||
@@ -566,7 +563,7 @@ static CURLcode pop3_perform_authentication(struct Curl_easy *data,
|
||||
}
|
||||
|
||||
if(!result && progress == SASL_IDLE) {
|
||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||
#ifndef CURL_DISABLE_DIGEST_AUTH
|
||||
if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_APOP)
|
||||
/* Perform APOP authentication */
|
||||
result = pop3_perform_apop(data, conn);
|
||||
@@ -834,7 +831,7 @@ static CURLcode pop3_state_auth_resp(struct Curl_easy *data,
|
||||
pop3_state(data, POP3_STOP); /* Authenticated */
|
||||
break;
|
||||
case SASL_IDLE: /* No mechanism left after cancellation */
|
||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||
#ifndef CURL_DISABLE_DIGEST_AUTH
|
||||
if(pop3c->authtypes & pop3c->preftype & POP3_TYPE_APOP)
|
||||
/* Perform APOP authentication */
|
||||
result = pop3_perform_apop(data, conn);
|
||||
@@ -855,7 +852,7 @@ static CURLcode pop3_state_auth_resp(struct Curl_easy *data,
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||
#ifndef CURL_DISABLE_DIGEST_AUTH
|
||||
/* For APOP responses */
|
||||
static CURLcode pop3_state_apop_resp(struct Curl_easy *data, int pop3code,
|
||||
pop3state instate)
|
||||
@@ -1018,7 +1015,7 @@ static CURLcode pop3_statemachine(struct Curl_easy *data,
|
||||
result = pop3_state_auth_resp(data, pop3code, pop3c->state);
|
||||
break;
|
||||
|
||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||
#ifndef CURL_DISABLE_DIGEST_AUTH
|
||||
case POP3_APOP:
|
||||
result = pop3_state_apop_resp(data, pop3code, pop3c->state);
|
||||
break;
|
||||
|
||||
@@ -36,6 +36,7 @@ uint32_t arc4random(void);
|
||||
#endif
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include "urldata.h"
|
||||
#include "vtls/vtls.h"
|
||||
#include "sendf.h"
|
||||
#include "timeval.h"
|
||||
@@ -187,7 +188,7 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
|
||||
* 'rnd' points to.
|
||||
*
|
||||
* If libcurl is built without TLS support or with a TLS backend that lacks a
|
||||
* proper random API (rustls, Gskit or mbedTLS), this function will use "weak"
|
||||
* proper random API (rustls or mbedTLS), this function will use "weak"
|
||||
* random.
|
||||
*
|
||||
* When built *with* TLS support and a backend that offers strong random, it
|
||||
|
||||
@@ -24,20 +24,6 @@
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/*
|
||||
* Curl_rand() stores 'num' number of random unsigned characters in the buffer
|
||||
* 'rnd' points to.
|
||||
*
|
||||
* If libcurl is built without TLS support or with a TLS backend that lacks a
|
||||
* proper random API (Gskit or mbedTLS), this function will use "weak" random.
|
||||
*
|
||||
* When built *with* TLS support and a backend that offers strong random, it
|
||||
* will return error if it cannot provide strong random values.
|
||||
*
|
||||
* NOTE: 'data' may be passed in as NULL when coming from external API without
|
||||
* easy handle!
|
||||
*
|
||||
*/
|
||||
CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num);
|
||||
|
||||
/*
|
||||
|
||||
@@ -138,6 +138,56 @@ static size_t convert_lineends(struct Curl_easy *data,
|
||||
}
|
||||
#endif /* CURL_DO_LINEEND_CONV && !CURL_DISABLE_FTP */
|
||||
|
||||
/*
|
||||
* Curl_nwrite() is an internal write function that sends data to the
|
||||
* server. Works with a socket index for the connection.
|
||||
*
|
||||
* If the write would block (CURLE_AGAIN), it returns CURLE_OK and
|
||||
* (*nwritten == 0). Otherwise we return regular CURLcode value.
|
||||
*/
|
||||
CURLcode Curl_nwrite(struct Curl_easy *data,
|
||||
int sockindex,
|
||||
const void *buf,
|
||||
size_t blen,
|
||||
ssize_t *pnwritten)
|
||||
{
|
||||
ssize_t nwritten;
|
||||
CURLcode result = CURLE_OK;
|
||||
struct connectdata *conn;
|
||||
|
||||
DEBUGASSERT(sockindex >= 0 && sockindex < 2);
|
||||
DEBUGASSERT(pnwritten);
|
||||
DEBUGASSERT(data);
|
||||
DEBUGASSERT(data->conn);
|
||||
conn = data->conn;
|
||||
#ifdef CURLDEBUG
|
||||
{
|
||||
/* Allow debug builds to override this logic to force short sends
|
||||
*/
|
||||
char *p = getenv("CURL_SMALLSENDS");
|
||||
if(p) {
|
||||
size_t altsize = (size_t)strtoul(p, NULL, 10);
|
||||
if(altsize)
|
||||
blen = CURLMIN(blen, altsize);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
nwritten = conn->send[sockindex](data, sockindex, buf, blen, &result);
|
||||
if(result == CURLE_AGAIN) {
|
||||
nwritten = 0;
|
||||
result = CURLE_OK;
|
||||
}
|
||||
else if(result) {
|
||||
nwritten = -1; /* make sure */
|
||||
}
|
||||
else {
|
||||
DEBUGASSERT(nwritten >= 0);
|
||||
}
|
||||
|
||||
*pnwritten = nwritten;
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_write() is an internal write function that sends data to the
|
||||
* server. Works with plain sockets, SCP, SSL or kerberos.
|
||||
@@ -151,48 +201,14 @@ CURLcode Curl_write(struct Curl_easy *data,
|
||||
size_t len,
|
||||
ssize_t *written)
|
||||
{
|
||||
ssize_t bytes_written;
|
||||
CURLcode result = CURLE_OK;
|
||||
struct connectdata *conn;
|
||||
int num;
|
||||
|
||||
DEBUGASSERT(data);
|
||||
DEBUGASSERT(data->conn);
|
||||
conn = data->conn;
|
||||
num = (sockfd != CURL_SOCKET_BAD && sockfd == conn->sock[SECONDARYSOCKET]);
|
||||
|
||||
#ifdef CURLDEBUG
|
||||
{
|
||||
/* Allow debug builds to override this logic to force short sends
|
||||
*/
|
||||
char *p = getenv("CURL_SMALLSENDS");
|
||||
if(p) {
|
||||
size_t altsize = (size_t)strtoul(p, NULL, 10);
|
||||
if(altsize)
|
||||
len = CURLMIN(len, altsize);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
bytes_written = conn->send[num](data, num, mem, len, &result);
|
||||
|
||||
*written = bytes_written;
|
||||
if(bytes_written >= 0)
|
||||
/* we completely ignore the curlcode value when subzero is not returned */
|
||||
return CURLE_OK;
|
||||
|
||||
/* handle CURLE_AGAIN or a send failure */
|
||||
switch(result) {
|
||||
case CURLE_AGAIN:
|
||||
*written = 0;
|
||||
return CURLE_OK;
|
||||
|
||||
case CURLE_OK:
|
||||
/* general send failure */
|
||||
return CURLE_SEND_ERROR;
|
||||
|
||||
default:
|
||||
/* we got a specific curlcode, forward it */
|
||||
return result;
|
||||
}
|
||||
return Curl_nwrite(data, num, mem, len, written);
|
||||
}
|
||||
|
||||
static CURLcode pausewrite(struct Curl_easy *data,
|
||||
@@ -421,4 +437,3 @@ CURLcode Curl_read(struct Curl_easy *data, /* transfer */
|
||||
out:
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#include "curl_log.h"
|
||||
#include "curl_trc.h"
|
||||
|
||||
|
||||
#define CLIENTWRITE_BODY (1<<0)
|
||||
@@ -51,4 +51,11 @@ CURLcode Curl_write(struct Curl_easy *data,
|
||||
const void *mem, size_t len,
|
||||
ssize_t *written);
|
||||
|
||||
/* internal write-function, using sockindex for connection destination */
|
||||
CURLcode Curl_nwrite(struct Curl_easy *data,
|
||||
int sockindex,
|
||||
const void *buf,
|
||||
size_t blen,
|
||||
ssize_t *pnwritten);
|
||||
|
||||
#endif /* HEADER_CURL_SENDF_H */
|
||||
|
||||
@@ -666,17 +666,20 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
data->set.method = HTTPREQ_GET;
|
||||
break;
|
||||
|
||||
#ifndef CURL_DISABLE_MIME
|
||||
#ifndef CURL_DISABLE_FORM_API
|
||||
case CURLOPT_HTTPPOST:
|
||||
/*
|
||||
* Set to make us do HTTP POST
|
||||
* Set to make us do HTTP POST. Legacy API-style.
|
||||
*/
|
||||
data->set.httppost = va_arg(param, struct curl_httppost *);
|
||||
data->set.method = HTTPREQ_POST_FORM;
|
||||
data->set.opt_no_body = FALSE; /* this is implied */
|
||||
Curl_mime_cleanpart(data->state.formp);
|
||||
Curl_safefree(data->state.formp);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if !defined(CURL_DISABLE_AWS)
|
||||
case CURLOPT_AWS_SIGV4:
|
||||
/*
|
||||
* String that is merged to some authentication
|
||||
@@ -690,6 +693,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
if(data->set.str[STRING_AWS_SIGV4])
|
||||
data->set.httpauth = CURLAUTH_AWS_SIGV4;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case CURLOPT_REFERER:
|
||||
/*
|
||||
@@ -985,6 +989,10 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
if(!result) {
|
||||
data->set.method = HTTPREQ_POST_MIME;
|
||||
data->set.opt_no_body = FALSE; /* this is implied */
|
||||
#ifndef CURL_DISABLE_FORM_API
|
||||
Curl_mime_cleanpart(data->state.formp);
|
||||
Curl_safefree(data->state.formp);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1237,6 +1245,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
data->set.out = va_arg(param, void *);
|
||||
break;
|
||||
|
||||
#ifdef CURL_LIST_ONLY_PROTOCOL
|
||||
case CURLOPT_DIRLISTONLY:
|
||||
/*
|
||||
* An option that changes the command to one that asks for a list only, no
|
||||
@@ -1244,7 +1253,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
*/
|
||||
data->set.list_only = (0 != va_arg(param, long)) ? TRUE : FALSE;
|
||||
break;
|
||||
|
||||
#endif
|
||||
case CURLOPT_APPEND:
|
||||
/*
|
||||
* We want to upload and append to an existing file. Used for FTP and
|
||||
@@ -1885,6 +1894,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
result = Curl_setstropt(&data->set.str[STRING_DEVICE],
|
||||
va_arg(param, char *));
|
||||
break;
|
||||
#ifndef CURL_DISABLE_BINDLOCAL
|
||||
case CURLOPT_LOCALPORT:
|
||||
/*
|
||||
* Set what local port to bind the socket to when performing an operation.
|
||||
@@ -1903,6 +1913,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
data->set.localportrange = curlx_sltous(arg);
|
||||
break;
|
||||
#endif
|
||||
case CURLOPT_GSSAPI_DELEGATION:
|
||||
/*
|
||||
* GSS-API credential delegation bitmask
|
||||
|
||||
@@ -34,6 +34,9 @@
|
||||
/* No OS/400 header file defines u_int32_t. */
|
||||
typedef unsigned long u_int32_t;
|
||||
|
||||
/* OS/400 has no idea of a tty! */
|
||||
#define isatty(fd) 0
|
||||
|
||||
|
||||
/* System API wrapper prototypes & definitions to support ASCII parameters. */
|
||||
|
||||
@@ -57,94 +60,6 @@ extern int Curl_getnameinfo_a(const struct sockaddr *sa,
|
||||
int flags);
|
||||
#define getnameinfo Curl_getnameinfo_a
|
||||
|
||||
|
||||
/* GSKit wrappers. */
|
||||
|
||||
extern int Curl_gsk_environment_open(gsk_handle * my_env_handle);
|
||||
#define gsk_environment_open Curl_gsk_environment_open
|
||||
|
||||
extern int Curl_gsk_secure_soc_open(gsk_handle my_env_handle,
|
||||
gsk_handle * my_session_handle);
|
||||
#define gsk_secure_soc_open Curl_gsk_secure_soc_open
|
||||
|
||||
extern int Curl_gsk_environment_close(gsk_handle * my_env_handle);
|
||||
#define gsk_environment_close Curl_gsk_environment_close
|
||||
|
||||
extern int Curl_gsk_secure_soc_close(gsk_handle * my_session_handle);
|
||||
#define gsk_secure_soc_close Curl_gsk_secure_soc_close
|
||||
|
||||
extern int Curl_gsk_environment_init(gsk_handle my_env_handle);
|
||||
#define gsk_environment_init Curl_gsk_environment_init
|
||||
|
||||
extern int Curl_gsk_secure_soc_init(gsk_handle my_session_handle);
|
||||
#define gsk_secure_soc_init Curl_gsk_secure_soc_init
|
||||
|
||||
extern int Curl_gsk_attribute_set_buffer_a(gsk_handle my_gsk_handle,
|
||||
GSK_BUF_ID bufID,
|
||||
const char *buffer,
|
||||
int bufSize);
|
||||
#define gsk_attribute_set_buffer Curl_gsk_attribute_set_buffer_a
|
||||
|
||||
extern int Curl_gsk_attribute_set_enum(gsk_handle my_gsk_handle,
|
||||
GSK_ENUM_ID enumID,
|
||||
GSK_ENUM_VALUE enumValue);
|
||||
#define gsk_attribute_set_enum Curl_gsk_attribute_set_enum
|
||||
|
||||
extern int Curl_gsk_attribute_set_numeric_value(gsk_handle my_gsk_handle,
|
||||
GSK_NUM_ID numID,
|
||||
int numValue);
|
||||
#define gsk_attribute_set_numeric_value Curl_gsk_attribute_set_numeric_value
|
||||
|
||||
extern int Curl_gsk_attribute_set_callback(gsk_handle my_gsk_handle,
|
||||
GSK_CALLBACK_ID callBackID,
|
||||
void *callBackAreaPtr);
|
||||
#define gsk_attribute_set_callback Curl_gsk_attribute_set_callback
|
||||
|
||||
extern int Curl_gsk_attribute_get_buffer_a(gsk_handle my_gsk_handle,
|
||||
GSK_BUF_ID bufID,
|
||||
const char **buffer,
|
||||
int *bufSize);
|
||||
#define gsk_attribute_get_buffer Curl_gsk_attribute_get_buffer_a
|
||||
|
||||
extern int Curl_gsk_attribute_get_enum(gsk_handle my_gsk_handle,
|
||||
GSK_ENUM_ID enumID,
|
||||
GSK_ENUM_VALUE *enumValue);
|
||||
#define gsk_attribute_get_enum Curl_gsk_attribute_get_enum
|
||||
|
||||
extern int Curl_gsk_attribute_get_numeric_value(gsk_handle my_gsk_handle,
|
||||
GSK_NUM_ID numID,
|
||||
int *numValue);
|
||||
#define gsk_attribute_get_numeric_value Curl_gsk_attribute_get_numeric_value
|
||||
|
||||
extern int Curl_gsk_attribute_get_cert_info(gsk_handle my_gsk_handle,
|
||||
GSK_CERT_ID certID,
|
||||
const gsk_cert_data_elem **certDataElem,
|
||||
int *certDataElementCount);
|
||||
#define gsk_attribute_get_cert_info Curl_gsk_attribute_get_cert_info
|
||||
|
||||
extern int Curl_gsk_secure_soc_misc(gsk_handle my_session_handle,
|
||||
GSK_MISC_ID miscID);
|
||||
#define gsk_secure_soc_misc Curl_gsk_secure_soc_misc
|
||||
|
||||
extern int Curl_gsk_secure_soc_read(gsk_handle my_session_handle,
|
||||
char *readBuffer,
|
||||
int readBufSize, int *amtRead);
|
||||
#define gsk_secure_soc_read Curl_gsk_secure_soc_read
|
||||
|
||||
extern int Curl_gsk_secure_soc_write(gsk_handle my_session_handle,
|
||||
char *writeBuffer,
|
||||
int writeBufSize, int *amtWritten);
|
||||
#define gsk_secure_soc_write Curl_gsk_secure_soc_write
|
||||
|
||||
extern const char * Curl_gsk_strerror_a(int gsk_return_value);
|
||||
#define gsk_strerror Curl_gsk_strerror_a
|
||||
|
||||
extern int Curl_gsk_secure_soc_startInit(gsk_handle my_session_handle,
|
||||
int IOCompletionPort,
|
||||
Qso_OverlappedIO_t * communicationsArea);
|
||||
#define gsk_secure_soc_startInit Curl_gsk_secure_soc_startInit
|
||||
|
||||
|
||||
/* GSSAPI wrappers. */
|
||||
|
||||
extern OM_uint32 Curl_gss_import_name_a(OM_uint32 * minor_status,
|
||||
|
||||
@@ -262,7 +262,6 @@ static struct passwd *vms_getpwuid(uid_t uid)
|
||||
#define PKCS12_parse PKCS12_PARSE
|
||||
#define RAND_add RAND_ADD
|
||||
#define RAND_bytes RAND_BYTES
|
||||
#define RAND_egd RAND_EGD
|
||||
#define RAND_file_name RAND_FILE_NAME
|
||||
#define RAND_load_file RAND_LOAD_FILE
|
||||
#define RAND_status RAND_STATUS
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||
#if !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH) \
|
||||
|| defined(USE_LIBSSH2)
|
||||
|
||||
#include "warnless.h"
|
||||
#include "curl_sha256.h"
|
||||
@@ -110,7 +111,10 @@ static CURLcode my_sha256_init(my_sha256_ctx *ctx)
|
||||
if(!ctx->openssl_ctx)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
EVP_DigestInit_ex(ctx->openssl_ctx, EVP_sha256(), NULL);
|
||||
if(!EVP_DigestInit_ex(ctx->openssl_ctx, EVP_sha256(), NULL)) {
|
||||
EVP_MD_CTX_destroy(ctx->openssl_ctx);
|
||||
return CURLE_FAILED_INIT;
|
||||
}
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
@@ -218,9 +222,14 @@ typedef struct sha256_ctx my_sha256_ctx;
|
||||
|
||||
static CURLcode my_sha256_init(my_sha256_ctx *ctx)
|
||||
{
|
||||
if(CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, PROV_RSA_AES,
|
||||
CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
|
||||
CryptCreateHash(ctx->hCryptProv, CALG_SHA_256, 0, 0, &ctx->hHash);
|
||||
if(!CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, PROV_RSA_AES,
|
||||
CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
if(!CryptCreateHash(ctx->hCryptProv, CALG_SHA_256, 0, 0, &ctx->hHash)) {
|
||||
CryptReleaseContext(ctx->hCryptProv, 0);
|
||||
ctx->hCryptProv = 0;
|
||||
return CURLE_FAILED_INIT;
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
@@ -533,4 +542,4 @@ const struct HMAC_params Curl_HMAC_SHA256[] = {
|
||||
};
|
||||
|
||||
|
||||
#endif /* CURL_DISABLE_CRYPTO_AUTH */
|
||||
#endif /* AWS, DIGEST, or libSSH2 */
|
||||
|
||||
@@ -564,12 +564,11 @@ static CURLcode smb_send(struct Curl_easy *data, ssize_t len,
|
||||
size_t upload_size)
|
||||
{
|
||||
struct connectdata *conn = data->conn;
|
||||
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
|
||||
struct smb_conn *smbc = &conn->proto.smbc;
|
||||
ssize_t bytes_written;
|
||||
CURLcode result;
|
||||
|
||||
result = Curl_write(data, sockfd, data->state.ulbuf,
|
||||
result = Curl_nwrite(data, FIRSTSOCKET, data->state.ulbuf,
|
||||
len, &bytes_written);
|
||||
if(result)
|
||||
return result;
|
||||
@@ -587,7 +586,6 @@ static CURLcode smb_send(struct Curl_easy *data, ssize_t len,
|
||||
static CURLcode smb_flush(struct Curl_easy *data)
|
||||
{
|
||||
struct connectdata *conn = data->conn;
|
||||
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
|
||||
struct smb_conn *smbc = &conn->proto.smbc;
|
||||
ssize_t bytes_written;
|
||||
ssize_t len = smbc->send_size - smbc->sent;
|
||||
@@ -596,9 +594,9 @@ static CURLcode smb_flush(struct Curl_easy *data)
|
||||
if(!smbc->send_size)
|
||||
return CURLE_OK;
|
||||
|
||||
result = Curl_write(data, sockfd,
|
||||
data->state.ulbuf + smbc->sent,
|
||||
len, &bytes_written);
|
||||
result = Curl_nwrite(data, FIRSTSOCKET,
|
||||
data->state.ulbuf + smbc->sent,
|
||||
len, &bytes_written);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
|
||||
@@ -49,9 +49,6 @@
|
||||
#ifdef HAVE_ARPA_INET_H
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
#ifdef HAVE_UTSNAME_H
|
||||
#include <sys/utsname.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
@@ -938,7 +938,7 @@ const char *Curl_winapi_strerror(DWORD err, char *buf, size_t buflen)
|
||||
|
||||
#ifndef CURL_DISABLE_VERBOSE_STRINGS
|
||||
if(!get_winapi_error(err, buf, buflen)) {
|
||||
msnprintf(buf, buflen, "Unknown error %u (0x%08X)", err, err);
|
||||
msnprintf(buf, buflen, "Unknown error %lu (0x%08lX)", err, err);
|
||||
}
|
||||
#else
|
||||
{
|
||||
|
||||
@@ -42,7 +42,8 @@ extern IF_NAMETOINDEX_FN Curl_if_nametoindex;
|
||||
|
||||
/* This is used to dynamically load DLLs */
|
||||
HMODULE Curl_load_library(LPCTSTR filename);
|
||||
|
||||
#endif /* WIN32 */
|
||||
#else /* WIN32 */
|
||||
#define Curl_win32_init(x) CURLE_OK
|
||||
#endif /* !WIN32 */
|
||||
|
||||
#endif /* HEADER_CURL_SYSTEM_WIN32_H */
|
||||
|
||||
@@ -1266,10 +1266,10 @@ static CURLcode send_telnet_data(struct Curl_easy *data,
|
||||
break;
|
||||
default: /* write! */
|
||||
bytes_written = 0;
|
||||
result = Curl_write(data, conn->sock[FIRSTSOCKET],
|
||||
outbuf + total_written,
|
||||
outlen - total_written,
|
||||
&bytes_written);
|
||||
result = Curl_nwrite(data, FIRSTSOCKET,
|
||||
outbuf + total_written,
|
||||
outlen - total_written,
|
||||
&bytes_written);
|
||||
total_written += bytes_written;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -431,6 +431,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
|
||||
curl_off_t max_recv = data->set.max_recv_speed?
|
||||
data->set.max_recv_speed : CURL_OFF_T_MAX;
|
||||
char *buf = data->state.buffer;
|
||||
bool data_eof_handled = FALSE;
|
||||
DEBUGASSERT(buf);
|
||||
|
||||
*done = FALSE;
|
||||
@@ -448,8 +449,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
|
||||
to ensure that http2_handle_stream_close is called when we read all
|
||||
incoming bytes for a particular stream. */
|
||||
bool is_http3 = Curl_conn_is_http3(data, conn, FIRSTSOCKET);
|
||||
bool data_eof_handled = is_http3
|
||||
|| Curl_conn_is_http2(data, conn, FIRSTSOCKET);
|
||||
data_eof_handled = is_http3 || Curl_conn_is_http2(data, conn, FIRSTSOCKET);
|
||||
|
||||
if(!data_eof_handled && k->size != -1 && !k->header) {
|
||||
/* make sure we don't read too much */
|
||||
@@ -492,15 +492,16 @@ static CURLcode readwrite_data(struct Curl_easy *data,
|
||||
if(0 < nread || is_empty_data) {
|
||||
buf[nread] = 0;
|
||||
}
|
||||
else {
|
||||
if(!nread) {
|
||||
/* if we receive 0 or less here, either the data transfer is done or the
|
||||
server closed the connection and we bail out from this! */
|
||||
if(data_eof_handled)
|
||||
DEBUGF(infof(data, "nread == 0, stream closed, bailing"));
|
||||
else
|
||||
DEBUGF(infof(data, "nread <= 0, server closed connection, bailing"));
|
||||
k->keepon &= ~KEEP_RECV;
|
||||
break;
|
||||
k->keepon = 0; /* stop sending as well */
|
||||
if(!is_empty_data)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Default buffer to use when we write the buffer, it may be changed
|
||||
@@ -761,7 +762,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
|
||||
}
|
||||
|
||||
if(((k->keepon & (KEEP_RECV|KEEP_SEND)) == KEEP_SEND) &&
|
||||
conn->bits.close) {
|
||||
(conn->bits.close || data_eof_handled)) {
|
||||
/* When we've read the entire thing and the close bit is set, the server
|
||||
may now close the connection. If there's now any kind of sending going
|
||||
on from our side, we need to stop that immediately. */
|
||||
@@ -824,9 +825,6 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
|
||||
bool sending_http_headers = FALSE;
|
||||
struct SingleRequest *k = &data->req;
|
||||
|
||||
if((k->bytecount == 0) && (k->writebytecount == 0))
|
||||
Curl_pgrsTime(data, TIMER_STARTTRANSFER);
|
||||
|
||||
*didwhat |= KEEP_SEND;
|
||||
|
||||
do {
|
||||
@@ -1335,7 +1333,9 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
|
||||
}
|
||||
|
||||
data->state.prefer_ascii = data->set.prefer_ascii;
|
||||
#ifdef CURL_LIST_ONLY_PROTOCOL
|
||||
data->state.list_only = data->set.list_only;
|
||||
#endif
|
||||
data->state.httpreq = data->set.method;
|
||||
data->state.url = data->set.str[STRING_SET_URL];
|
||||
|
||||
@@ -1397,7 +1397,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
|
||||
Curl_pgrsResetTransferSizes(data);
|
||||
Curl_pgrsStartNow(data);
|
||||
|
||||
/* In case the handle is re-used and an authentication method was picked
|
||||
/* In case the handle is reused and an authentication method was picked
|
||||
in the session we need to make sure we only use the one(s) we now
|
||||
consider to be fine */
|
||||
data->state.authhost.picked &= data->state.authhost.want;
|
||||
@@ -1787,7 +1787,7 @@ CURLcode Curl_retry_request(struct Curl_easy *data, char **url)
|
||||
&& (data->set.rtspreq != RTSPREQ_RECEIVE)
|
||||
#endif
|
||||
)
|
||||
/* We got no data, we attempted to re-use a connection. For HTTP this
|
||||
/* We got no data, we attempted to reuse a connection. For HTTP this
|
||||
can be a retry so we try again regardless if we expected a body.
|
||||
For other protocols we only try again only if we expected a body.
|
||||
|
||||
|
||||
+45
-35
@@ -414,7 +414,7 @@ CURLcode Curl_close(struct Curl_easy **datap)
|
||||
Curl_hsts_cleanup(&data->hsts);
|
||||
curl_slist_free_all(data->set.hstslist); /* clean up list */
|
||||
#endif
|
||||
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
|
||||
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_DIGEST_AUTH)
|
||||
Curl_http_auth_cleanup_digest(data);
|
||||
#endif
|
||||
Curl_safefree(data->info.contenttype);
|
||||
@@ -457,6 +457,11 @@ CURLcode Curl_close(struct Curl_easy **datap)
|
||||
}
|
||||
#endif
|
||||
|
||||
Curl_mime_cleanpart(data->state.formp);
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
Curl_safefree(data->state.formp);
|
||||
#endif
|
||||
|
||||
/* destruct wildcard structures if it is needed */
|
||||
Curl_wildcard_dtor(&data->wildcard);
|
||||
Curl_freeset(data);
|
||||
@@ -490,7 +495,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
|
||||
|
||||
set->filesize = -1; /* we don't know the size */
|
||||
set->postfieldsize = -1; /* unknown size */
|
||||
set->maxredirs = -1; /* allow any amount by default */
|
||||
set->maxredirs = 30; /* sensible default */
|
||||
|
||||
set->method = HTTPREQ_GET; /* Default HTTP request */
|
||||
#ifndef CURL_DISABLE_RTSP
|
||||
@@ -948,7 +953,7 @@ static bool extract_if_dead(struct connectdata *conn,
|
||||
* that we expect - in general - no waiting input data. Input
|
||||
* waiting might be a TLS Notify Close, for example. We reject
|
||||
* that.
|
||||
* For protocols where data from other other end may arrive at
|
||||
* For protocols where data from other end may arrive at
|
||||
* any time (HTTP/2 PING for example), the protocol handler needs
|
||||
* to install its own `connection_check` callback.
|
||||
*/
|
||||
@@ -1073,6 +1078,9 @@ ConnectionExists(struct Curl_easy *data,
|
||||
bool wantProxyNTLMhttp = FALSE;
|
||||
#endif
|
||||
#endif
|
||||
/* plain HTTP with upgrade */
|
||||
bool h2upgrade = (data->state.httpwant == CURL_HTTP_VERSION_2_0) &&
|
||||
(needle->handler->protocol & CURLPROTO_HTTP);
|
||||
|
||||
*force_reuse = FALSE;
|
||||
*waitpipe = FALSE;
|
||||
@@ -1095,7 +1103,7 @@ ConnectionExists(struct Curl_easy *data,
|
||||
infof(data, "Server doesn't support multiplex yet, wait");
|
||||
*waitpipe = TRUE;
|
||||
CONNCACHE_UNLOCK(data);
|
||||
return FALSE; /* no re-use */
|
||||
return FALSE; /* no reuse */
|
||||
}
|
||||
|
||||
infof(data, "Server doesn't support multiplex (yet)");
|
||||
@@ -1135,7 +1143,7 @@ ConnectionExists(struct Curl_easy *data,
|
||||
}
|
||||
|
||||
if(data->set.ipver != CURL_IPRESOLVE_WHATEVER
|
||||
&& data->set.ipver != check->ip_version) {
|
||||
&& data->set.ipver != check->ip_version) {
|
||||
/* skip because the connection is not via the requested IP version */
|
||||
continue;
|
||||
}
|
||||
@@ -1150,16 +1158,11 @@ ConnectionExists(struct Curl_easy *data,
|
||||
continue;
|
||||
}
|
||||
|
||||
if(Curl_resolver_asynch()) {
|
||||
/* primary_ip[0] is NUL only if the resolving of the name hasn't
|
||||
completed yet and until then we don't re-use this connection */
|
||||
if(!check->primary_ip[0]) {
|
||||
infof(data, "Connection #%" CURL_FORMAT_CURL_OFF_T " is still "
|
||||
"name resolving, can't reuse",
|
||||
check->connection_id);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if(Curl_resolver_asynch() &&
|
||||
/* primary_ip[0] is NUL only if the resolving of the name hasn't
|
||||
completed yet and until then we don't reuse this connection */
|
||||
!check->primary_ip[0])
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!Curl_conn_is_connected(check, FIRSTSOCKET)) {
|
||||
@@ -1238,6 +1241,17 @@ ConnectionExists(struct Curl_easy *data,
|
||||
}
|
||||
#endif
|
||||
|
||||
if(h2upgrade && !check->httpversion && canmultiplex) {
|
||||
if(data->set.pipewait) {
|
||||
infof(data, "Server upgrade doesn't support multiplex yet, wait");
|
||||
*waitpipe = TRUE;
|
||||
CONNCACHE_UNLOCK(data);
|
||||
return FALSE; /* no reuse */
|
||||
}
|
||||
infof(data, "Server upgrade cannot be used");
|
||||
continue; /* can't be used atm */
|
||||
}
|
||||
|
||||
if(!canmultiplex && CONN_INUSE(check))
|
||||
/* this request can't be multiplexed but the checked connection is
|
||||
already in use so we skip it */
|
||||
@@ -1254,14 +1268,14 @@ ConnectionExists(struct Curl_easy *data,
|
||||
|
||||
if(needle->localdev || needle->localport) {
|
||||
/* If we are bound to a specific local end (IP+port), we must not
|
||||
re-use a random other one, although if we didn't ask for a
|
||||
reuse a random other one, although if we didn't ask for a
|
||||
particular one we can reuse one that was bound.
|
||||
|
||||
This comparison is a bit rough and too strict. Since the input
|
||||
parameters can be specified in numerous ways and still end up the
|
||||
same it would take a lot of processing to make it really accurate.
|
||||
Instead, this matching will assume that re-uses of bound connections
|
||||
will most likely also re-use the exact same binding parameters and
|
||||
Instead, this matching will assume that reuses of bound connections
|
||||
will most likely also reuse the exact same binding parameters and
|
||||
missing out a few edge cases shouldn't hurt anyone very much.
|
||||
*/
|
||||
if((check->localport != needle->localport) ||
|
||||
@@ -1294,7 +1308,7 @@ ConnectionExists(struct Curl_easy *data,
|
||||
(((check->httpversion >= 20) &&
|
||||
(data->state.httpwant < CURL_HTTP_VERSION_2_0))
|
||||
|| ((check->httpversion >= 30) &&
|
||||
(data->state.httpwant < CURL_HTTP_VERSION_3))))
|
||||
(data->state.httpwant < CURL_HTTP_VERSION_3))))
|
||||
continue;
|
||||
#ifdef USE_SSH
|
||||
else if(get_protocol_family(needle->handler) & PROTO_FAMILY_SSH) {
|
||||
@@ -1485,13 +1499,7 @@ void Curl_verboseconnect(struct Curl_easy *data,
|
||||
{
|
||||
if(data->set.verbose)
|
||||
infof(data, "Connected to %s (%s) port %u",
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
conn->bits.socksproxy ? conn->socks_proxy.host.dispname :
|
||||
conn->bits.httpproxy ? conn->http_proxy.host.dispname :
|
||||
#endif
|
||||
conn->bits.conn_to_host ? conn->conn_to_host.dispname :
|
||||
conn->host.dispname,
|
||||
conn->primary_ip, conn->port);
|
||||
CURL_CONN_HOST_DISPNAME(conn), conn->primary_ip, conn->port);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1587,8 +1595,10 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
|
||||
if(!conn->localdev)
|
||||
goto error;
|
||||
}
|
||||
#ifndef CURL_DISABLE_BINDLOCAL
|
||||
conn->localportrange = data->set.localportrange;
|
||||
conn->localport = data->set.localport;
|
||||
#endif
|
||||
|
||||
/* the close socket stuff needs to be copied to the connection struct as
|
||||
it may live on without (this specific) Curl_easy */
|
||||
@@ -2120,7 +2130,7 @@ static char *detect_proxy(struct Curl_easy *data,
|
||||
|
||||
/*
|
||||
* If this is supposed to use a proxy, we need to figure out the proxy
|
||||
* host name, so that we can re-use an existing connection
|
||||
* host name, so that we can reuse an existing connection
|
||||
* that may exist registered to the same proxy host.
|
||||
*/
|
||||
static CURLcode parse_proxy(struct Curl_easy *data,
|
||||
@@ -2441,7 +2451,7 @@ static CURLcode create_conn_helper_init_proxy(struct Curl_easy *data,
|
||||
|
||||
/***********************************************************************
|
||||
* If this is supposed to use a proxy, we need to figure out the proxy host
|
||||
* name, proxy type and port number, so that we can re-use an existing
|
||||
* name, proxy type and port number, so that we can reuse an existing
|
||||
* connection that may exist registered to the same proxy host.
|
||||
***********************************************************************/
|
||||
if(proxy || socksproxy) {
|
||||
@@ -3259,7 +3269,7 @@ static CURLcode resolve_server(struct Curl_easy *data,
|
||||
/* Resolve the name of the server or proxy */
|
||||
if(conn->bits.reuse) {
|
||||
/* We're reusing the connection - no need to resolve anything, and
|
||||
idnconvert_hostname() was called already in create_conn() for the re-use
|
||||
idnconvert_hostname() was called already in create_conn() for the reuse
|
||||
case. */
|
||||
*async = FALSE;
|
||||
return CURLE_OK;
|
||||
@@ -3278,7 +3288,7 @@ static void reuse_conn(struct Curl_easy *data,
|
||||
struct connectdata *existing)
|
||||
{
|
||||
/* get the user+password information from the temp struct since it may
|
||||
* be new for this request even when we re-use an existing connection */
|
||||
* be new for this request even when we reuse an existing connection */
|
||||
if(temp->user) {
|
||||
/* use the new user name and password though */
|
||||
Curl_safefree(existing->user);
|
||||
@@ -3338,14 +3348,14 @@ static void reuse_conn(struct Curl_easy *data,
|
||||
existing->hostname_resolve = temp->hostname_resolve;
|
||||
temp->hostname_resolve = NULL;
|
||||
|
||||
/* re-use init */
|
||||
existing->bits.reuse = TRUE; /* yes, we're re-using here */
|
||||
/* reuse init */
|
||||
existing->bits.reuse = TRUE; /* yes, we're reusing here */
|
||||
|
||||
conn_free(data, temp);
|
||||
}
|
||||
|
||||
/**
|
||||
* create_conn() sets up a new connectdata struct, or re-uses an already
|
||||
* create_conn() sets up a new connectdata struct, or reuses an already
|
||||
* existing one, and resolves host name.
|
||||
*
|
||||
* if this function returns CURLE_OK and *async is set to TRUE, the resolve
|
||||
@@ -3657,7 +3667,7 @@ static CURLcode create_conn(struct Curl_easy *data,
|
||||
|
||||
/*************************************************************
|
||||
* Check the current list of connections to see if we can
|
||||
* re-use an already existing one or if we have to create a
|
||||
* reuse an already existing one or if we have to create a
|
||||
* new one.
|
||||
*************************************************************/
|
||||
|
||||
@@ -3665,7 +3675,7 @@ static CURLcode create_conn(struct Curl_easy *data,
|
||||
DEBUGASSERT(conn->passwd);
|
||||
|
||||
/* reuse_fresh is TRUE if we are told to use a new connection by force, but
|
||||
we only acknowledge this option if this is not a re-used connection
|
||||
we only acknowledge this option if this is not a reused connection
|
||||
already (which happens due to follow-location or during an HTTP
|
||||
authentication phase). CONNECT_ONLY transfers also refuse reuse. */
|
||||
if((data->set.reuse_fresh && !data->state.followlocation) ||
|
||||
|
||||
@@ -1109,6 +1109,7 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags)
|
||||
if('/' == path[0] && STARTS_WITH_URL_DRIVE_PREFIX(&path[1])) {
|
||||
/* This cannot be done with strcpy, as the memory chunks overlap! */
|
||||
path++;
|
||||
pathlen--;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1384,6 +1385,7 @@ CURLU *curl_url_dup(const CURLU *in)
|
||||
DUP(u, in, path);
|
||||
DUP(u, in, query);
|
||||
DUP(u, in, fragment);
|
||||
DUP(u, in, zoneid);
|
||||
u->portnum = in->portnum;
|
||||
}
|
||||
return u;
|
||||
@@ -1401,6 +1403,7 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
|
||||
bool urldecode = (flags & CURLU_URLDECODE)?1:0;
|
||||
bool urlencode = (flags & CURLU_URLENCODE)?1:0;
|
||||
bool punycode = FALSE;
|
||||
bool depunyfy = FALSE;
|
||||
bool plusdecode = FALSE;
|
||||
(void)flags;
|
||||
if(!u)
|
||||
@@ -1431,6 +1434,7 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
|
||||
ptr = u->host;
|
||||
ifmissing = CURLUE_NO_HOST;
|
||||
punycode = (flags & CURLU_PUNYCODE)?1:0;
|
||||
depunyfy = (flags & CURLU_PUNY2IDN)?1:0;
|
||||
break;
|
||||
case CURLUPART_ZONEID:
|
||||
ptr = u->zoneid;
|
||||
@@ -1481,6 +1485,7 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
|
||||
char *port = u->port;
|
||||
char *allochost = NULL;
|
||||
punycode = (flags & CURLU_PUNYCODE)?1:0;
|
||||
depunyfy = (flags & CURLU_PUNY2IDN)?1:0;
|
||||
if(u->scheme && strcasecompare("file", u->scheme)) {
|
||||
url = aprintf("file://%s%s%s",
|
||||
u->path,
|
||||
@@ -1540,9 +1545,23 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
|
||||
#ifndef USE_IDN
|
||||
return CURLUE_LACKS_IDN;
|
||||
#else
|
||||
allochost = Curl_idn_decode(u->host);
|
||||
if(!allochost)
|
||||
return CURLUE_OUT_OF_MEMORY;
|
||||
CURLcode result = Curl_idn_decode(u->host, &allochost);
|
||||
if(result)
|
||||
return (result == CURLE_OUT_OF_MEMORY) ?
|
||||
CURLUE_OUT_OF_MEMORY : CURLUE_BAD_HOSTNAME;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if(depunyfy) {
|
||||
if(Curl_is_ASCII_name(u->host) && !strncmp("xn--", u->host, 4)) {
|
||||
#ifndef USE_IDN
|
||||
return CURLUE_LACKS_IDN;
|
||||
#else
|
||||
CURLcode result = Curl_idn_encode(u->host, &allochost);
|
||||
if(result)
|
||||
/* this is the most likely error */
|
||||
return (result == CURLE_OUT_OF_MEMORY) ?
|
||||
CURLUE_OUT_OF_MEMORY : CURLUE_BAD_HOSTNAME;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -1616,9 +1635,26 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
|
||||
#ifndef USE_IDN
|
||||
return CURLUE_LACKS_IDN;
|
||||
#else
|
||||
char *allochost = Curl_idn_decode(*part);
|
||||
if(!allochost)
|
||||
return CURLUE_OUT_OF_MEMORY;
|
||||
char *allochost;
|
||||
CURLcode result = Curl_idn_decode(*part, &allochost);
|
||||
if(result)
|
||||
return (result == CURLE_OUT_OF_MEMORY) ?
|
||||
CURLUE_OUT_OF_MEMORY : CURLUE_BAD_HOSTNAME;
|
||||
free(*part);
|
||||
*part = allochost;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if(depunyfy) {
|
||||
if(Curl_is_ASCII_name(u->host) && !strncmp("xn--", u->host, 4)) {
|
||||
#ifndef USE_IDN
|
||||
return CURLUE_LACKS_IDN;
|
||||
#else
|
||||
char *allochost;
|
||||
CURLcode result = Curl_idn_encode(*part, &allochost);
|
||||
if(result)
|
||||
return (result == CURLE_OUT_OF_MEMORY) ?
|
||||
CURLUE_OUT_OF_MEMORY : CURLUE_BAD_HOSTNAME;
|
||||
free(*part);
|
||||
*part = allochost;
|
||||
#endif
|
||||
@@ -1780,6 +1816,10 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
|
||||
char *oldurl;
|
||||
char *redired_url;
|
||||
|
||||
if(!nalloc)
|
||||
/* a blank URL is not a valid URL */
|
||||
return CURLUE_MALFORMED_INPUT;
|
||||
|
||||
/* if the new thing is absolute or the old one is not
|
||||
* (we could not get an absolute url in 'oldurl'),
|
||||
* then replace the existing with the new. */
|
||||
|
||||
@@ -101,6 +101,12 @@ typedef unsigned int curl_prot_t;
|
||||
#define PROTO_FAMILY_SMTP (CURLPROTO_SMTP|CURLPROTO_SMTPS)
|
||||
#define PROTO_FAMILY_SSH (CURLPROTO_SCP|CURLPROTO_SFTP)
|
||||
|
||||
#if !defined(CURL_DISABLE_FTP) || defined(USE_SSH) || \
|
||||
!defined(CURL_DISABLE_POP3)
|
||||
/* these protocols support CURLOPT_DIRLISTONLY */
|
||||
#define CURL_LIST_ONLY_PROTOCOL 1
|
||||
#endif
|
||||
|
||||
#define DEFAULT_CONNCACHE_SIZE 5
|
||||
|
||||
/* length of longest IPv6 address string including the trailing null */
|
||||
@@ -330,6 +336,7 @@ struct Curl_ssl_session {
|
||||
#include "curl_sspi.h"
|
||||
#endif
|
||||
|
||||
#ifndef CURL_DISABLE_DIGEST_AUTH
|
||||
/* Struct used for Digest challenge-response authentication */
|
||||
struct digestdata {
|
||||
#if defined(USE_WINDOWS_SSPI)
|
||||
@@ -353,6 +360,7 @@ struct digestdata {
|
||||
BIT(userhash);
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
NTLMSTATE_NONE,
|
||||
@@ -489,7 +497,7 @@ struct ConnectBits {
|
||||
#endif
|
||||
/* always modify bits.close with the connclose() and connkeep() macros! */
|
||||
BIT(close); /* if set, we close the connection after this request */
|
||||
BIT(reuse); /* if set, this is a re-used connection */
|
||||
BIT(reuse); /* if set, this is a reused connection */
|
||||
BIT(altused); /* this is an alt-svc "redirect" */
|
||||
BIT(conn_to_host); /* if set, this connection has a "connect to host"
|
||||
that overrides the host in the URL */
|
||||
@@ -629,17 +637,16 @@ struct SingleRequest {
|
||||
curl_off_t bytecount; /* total number of bytes read */
|
||||
curl_off_t writebytecount; /* number of bytes written */
|
||||
|
||||
curl_off_t headerbytecount; /* only count received headers */
|
||||
curl_off_t 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
|
||||
counter to make only a 100 reply (without a
|
||||
following second response code) result in a
|
||||
CURLE_GOT_NOTHING error code */
|
||||
|
||||
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 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
|
||||
counter to make only a 100 reply (without
|
||||
a following second response code) result
|
||||
in a CURLE_GOT_NOTHING error code */
|
||||
enum {
|
||||
HEADER_NORMAL, /* no bad header at all */
|
||||
HEADER_PARTHEADER, /* part of the chunk is a bad header, the rest
|
||||
@@ -701,7 +708,9 @@ struct SingleRequest {
|
||||
struct curltime last_sndbuf_update; /* last time readwrite_upload called
|
||||
win_update_buffer_size */
|
||||
#endif
|
||||
#ifndef CURL_DISABLE_COOKIES
|
||||
unsigned char setcookies;
|
||||
#endif
|
||||
unsigned char writer_stack_depth; /* Unencoding stack depth. */
|
||||
BIT(header); /* incoming data has HTTP header */
|
||||
BIT(content_range); /* set TRUE if Content-Range: was found */
|
||||
@@ -747,7 +756,7 @@ struct Curl_handler {
|
||||
* after the connect() and everything is done, as a step in the connection.
|
||||
* The 'done' pointer points to a bool that should be set to TRUE if the
|
||||
* function completes before return. If it doesn't complete, the caller
|
||||
* should call the curl_connecting() function until it is.
|
||||
* should call the ->connecting() function until it is.
|
||||
*/
|
||||
CURLcode (*connect_it)(struct Curl_easy *data, bool *done);
|
||||
|
||||
@@ -887,7 +896,7 @@ struct connectdata {
|
||||
|
||||
/* 'dns_entry' is the particular host we use. This points to an entry in the
|
||||
DNS cache and it will not get pruned while locked. It gets unlocked in
|
||||
multi_done(). This entry will be NULL if the connection is re-used as then
|
||||
multi_done(). This entry will be NULL if the connection is reused as then
|
||||
there is no name resolve done. */
|
||||
struct Curl_dns_entry *dns_entry;
|
||||
|
||||
@@ -1024,14 +1033,19 @@ struct connectdata {
|
||||
#ifndef CURL_DISABLE_SMB
|
||||
struct smb_conn smbc;
|
||||
#endif
|
||||
#ifdef USE_LIBRTMP
|
||||
void *rtmp;
|
||||
#endif
|
||||
#ifdef USE_OPENLDAP
|
||||
struct ldapconninfo *ldapc;
|
||||
#endif
|
||||
#ifndef CURL_DISABLE_MQTT
|
||||
struct mqtt_conn mqtt;
|
||||
#endif
|
||||
#ifdef USE_WEBSOCKETS
|
||||
struct websocket *ws;
|
||||
#endif
|
||||
unsigned int unused:1; /* avoids empty union */
|
||||
} proto;
|
||||
|
||||
struct connectbundle *bundle; /* The bundle we are member of */
|
||||
@@ -1045,7 +1059,7 @@ struct connectdata {
|
||||
/* When this connection is created, store the conditions for the local end
|
||||
bind. This is stored before the actual bind and before any connection is
|
||||
made and will serve the purpose of being used for comparison reasons so
|
||||
that subsequent bound-requested connections aren't accidentally re-using
|
||||
that subsequent bound-requested connections aren't accidentally reusing
|
||||
wrong connections. */
|
||||
char *localdev;
|
||||
unsigned short localportrange;
|
||||
@@ -1077,6 +1091,18 @@ struct connectdata {
|
||||
unsigned char gssapi_delegation; /* inherited from set.gssapi_delegation */
|
||||
};
|
||||
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
#define CURL_CONN_HOST_DISPNAME(c) \
|
||||
((c)->bits.socksproxy ? (c)->socks_proxy.host.dispname : \
|
||||
(c)->bits.httpproxy ? (c)->http_proxy.host.dispname : \
|
||||
(c)->bits.conn_to_host ? (c)->conn_to_host.dispname : \
|
||||
(c)->host.dispname)
|
||||
#else
|
||||
#define CURL_CONN_HOST_DISPNAME(c) \
|
||||
(c)->bits.conn_to_host ? (c)->conn_to_host.dispname : \
|
||||
(c)->host.dispname
|
||||
#endif
|
||||
|
||||
/* The end of connectdata. */
|
||||
|
||||
/*
|
||||
@@ -1089,7 +1115,6 @@ struct PureInfo {
|
||||
int httpversion; /* the http version number X.Y = X*10+Y */
|
||||
time_t filetime; /* If requested, this is might get set. Set to -1 if the
|
||||
time was unretrievable. */
|
||||
curl_off_t header_size; /* size of read header(s) in bytes */
|
||||
curl_off_t request_size; /* the amount of bytes sent in the request(s) */
|
||||
unsigned long proxyauthavail; /* what proxy auth types were announced */
|
||||
unsigned long httpauthavail; /* what host auth types were announced */
|
||||
@@ -1097,6 +1122,7 @@ struct PureInfo {
|
||||
char *contenttype; /* the content type of the object */
|
||||
char *wouldredirect; /* URL this would've been redirected to if asked to */
|
||||
curl_off_t retry_after; /* info from Retry-After: header */
|
||||
unsigned int header_size; /* size of read header(s) in bytes */
|
||||
|
||||
/* PureInfo members 'conn_primary_ip', 'conn_primary_port', 'conn_local_ip'
|
||||
and, 'conn_local_port' are copied over from the connectdata struct in
|
||||
@@ -1116,10 +1142,8 @@ struct PureInfo {
|
||||
int conn_local_port;
|
||||
const char *conn_scheme;
|
||||
unsigned int conn_protocol;
|
||||
struct curl_certinfo certs; /* info about the certs, only populated in
|
||||
OpenSSL, GnuTLS, Schannel, NSS and GSKit
|
||||
builds. Asked for with CURLOPT_CERTINFO
|
||||
/ CURLINFO_CERTINFO */
|
||||
struct curl_certinfo certs; /* info about the certs. Asked for with
|
||||
CURLOPT_CERTINFO / CURLINFO_CERTINFO */
|
||||
CURLproxycode pxcode;
|
||||
BIT(timecond); /* set to TRUE if the time condition didn't match, which
|
||||
thus made the document NOT get fetched */
|
||||
@@ -1325,7 +1349,7 @@ struct UrlState {
|
||||
/* storage for the previous bag^H^H^HSIGPIPE signal handler :-) */
|
||||
void (*prev_signal)(int sig);
|
||||
#endif
|
||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||
#ifndef CURL_DISABLE_DIGEST_AUTH
|
||||
struct digestdata digest; /* state data for host Digest auth */
|
||||
struct digestdata proxydigest; /* state data for proxy Digest auth */
|
||||
#endif
|
||||
@@ -1383,6 +1407,9 @@ struct UrlState {
|
||||
struct curl_slist *resolve; /* set to point to the set.resolve list when
|
||||
this should be dealt with in pretransfer */
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
curl_mimepart *mimepost;
|
||||
curl_mimepart *formp; /* storage for old API form-posting, alloced on
|
||||
demand */
|
||||
size_t trailers_bytes_sent;
|
||||
struct dynbuf trailers_buf; /* a buffer containing the compiled trailing
|
||||
headers */
|
||||
@@ -1454,9 +1481,13 @@ struct UrlState {
|
||||
when multi_done() is called, to prevent multi_done() to get
|
||||
invoked twice when the multi interface is used. */
|
||||
BIT(previouslypending); /* this transfer WAS in the multi->pending queue */
|
||||
#ifndef CURL_DISABLE_COOKIES
|
||||
BIT(cookie_engine);
|
||||
#endif
|
||||
BIT(prefer_ascii); /* ASCII rather than binary */
|
||||
#ifdef CURL_LIST_ONLY_PROTOCOL
|
||||
BIT(list_only); /* list directory contents */
|
||||
#endif
|
||||
BIT(url_alloc); /* URL string is malloc()'ed */
|
||||
BIT(referer_alloc); /* referer string is malloc()ed */
|
||||
BIT(wildcard_resolve); /* Set to true if any resolve change is a wildcard */
|
||||
@@ -1613,10 +1644,12 @@ struct UserDefined {
|
||||
curl_off_t postfieldsize; /* if POST, this might have a size to use instead
|
||||
of strlen(), and then the data *may* be binary
|
||||
(contain zero bytes) */
|
||||
#ifndef CURL_DISABLE_BINDLOCAL
|
||||
unsigned short localport; /* local port number to bind to */
|
||||
unsigned short localportrange; /* number of additional port numbers to test
|
||||
in case the 'localport' one can't be
|
||||
bind()ed */
|
||||
#endif
|
||||
curl_write_callback fwrite_func; /* function that stores the output */
|
||||
curl_write_callback fwrite_header; /* function that stores headers */
|
||||
curl_write_callback fwrite_rtp; /* function that stores interleaved RTP */
|
||||
@@ -1804,7 +1837,9 @@ struct UserDefined {
|
||||
BIT(tftp_no_options); /* do not send TFTP options requests */
|
||||
#endif
|
||||
BIT(sep_headers); /* handle host and proxy headers separately */
|
||||
#ifndef CURL_DISABLE_COOKIES
|
||||
BIT(cookiesession); /* new cookie session? */
|
||||
#endif
|
||||
BIT(crlf); /* convert crlf on ftp upload(?) */
|
||||
BIT(ssh_compression); /* enable SSH compression */
|
||||
|
||||
@@ -1819,7 +1854,9 @@ struct UserDefined {
|
||||
BIT(tunnel_thru_httpproxy); /* use CONNECT through an HTTP proxy */
|
||||
BIT(prefer_ascii); /* ASCII rather than binary */
|
||||
BIT(remote_append); /* append, not overwrite, on upload */
|
||||
#ifdef CURL_LIST_ONLY_PROTOCOL
|
||||
BIT(list_only); /* list directory */
|
||||
#endif
|
||||
#ifndef CURL_DISABLE_FTP
|
||||
BIT(ftp_use_port); /* use the FTP PORT command */
|
||||
BIT(ftp_use_epsv); /* if EPSV is to be attempted or not */
|
||||
@@ -1843,7 +1880,7 @@ struct UserDefined {
|
||||
BIT(verbose); /* output verbosity */
|
||||
BIT(krb); /* Kerberos connection requested */
|
||||
BIT(reuse_forbid); /* forbidden to be reused, close after use */
|
||||
BIT(reuse_fresh); /* do not re-use an existing connection */
|
||||
BIT(reuse_fresh); /* do not reuse an existing connection */
|
||||
BIT(no_signal); /* do not use any signal/alarm handler */
|
||||
BIT(tcp_nodelay); /* whether to enable TCP_NODELAY or not */
|
||||
BIT(ignorecl); /* ignore content length */
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#if !defined(CURL_DISABLE_CRYPTO_AUTH)
|
||||
#ifndef CURL_DISABLE_DIGEST_AUTH
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include "urldata.h"
|
||||
@@ -94,4 +94,4 @@ CURLcode Curl_auth_create_cram_md5_message(const struct bufref *chlg,
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
#endif /* !CURL_DISABLE_CRYPTO_AUTH */
|
||||
#endif /* !CURL_DISABLE_DIGEST_AUTH */
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#if !defined(CURL_DISABLE_CRYPTO_AUTH)
|
||||
#ifndef CURL_DISABLE_DIGEST_AUTH
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
@@ -420,7 +420,7 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
|
||||
msnprintf(&HA1_hex[2 * i], 3, "%02x", digest[i]);
|
||||
|
||||
/* Generate our SPN */
|
||||
spn = Curl_auth_build_spn(service, realm, NULL);
|
||||
spn = Curl_auth_build_spn(service, data->conn->host.name, NULL);
|
||||
if(!spn)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
@@ -992,4 +992,4 @@ void Curl_auth_digest_cleanup(struct digestdata *digest)
|
||||
}
|
||||
#endif /* !USE_WINDOWS_SSPI */
|
||||
|
||||
#endif /* CURL_DISABLE_CRYPTO_AUTH */
|
||||
#endif /* !CURL_DISABLE_DIGEST_AUTH */
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#if !defined(CURL_DISABLE_CRYPTO_AUTH)
|
||||
#ifndef CURL_DISABLE_DIGEST_AUTH
|
||||
|
||||
#define DIGEST_MAX_VALUE_LENGTH 256
|
||||
#define DIGEST_MAX_CONTENT_LENGTH 1024
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#if defined(USE_WINDOWS_SSPI) && !defined(CURL_DISABLE_CRYPTO_AUTH)
|
||||
#if defined(USE_WINDOWS_SSPI) && !defined(CURL_DISABLE_DIGEST_AUTH)
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
@@ -665,4 +665,4 @@ void Curl_auth_digest_cleanup(struct digestdata *digest)
|
||||
Curl_safefree(digest->passwd);
|
||||
}
|
||||
|
||||
#endif /* USE_WINDOWS_SSPI && !CURL_DISABLE_CRYPTO_AUTH */
|
||||
#endif /* USE_WINDOWS_SSPI && !CURL_DISABLE_DIGEST_AUTH */
|
||||
|
||||
@@ -45,12 +45,6 @@
|
||||
#include "rand.h"
|
||||
#include "vtls/vtls.h"
|
||||
|
||||
/* SSL backend-specific #if branches in this file must be kept in the order
|
||||
documented in curl_ntlm_core. */
|
||||
#if defined(NTLM_NEEDS_NSS_INIT)
|
||||
#include "vtls/nssg.h" /* for Curl_nss_force_init() */
|
||||
#endif
|
||||
|
||||
#define BUILDING_CURL_NTLM_MSGS_C
|
||||
#include "vauth/vauth.h"
|
||||
#include "vauth/ntlm.h"
|
||||
@@ -274,12 +268,7 @@ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data,
|
||||
const unsigned char *type2 = Curl_bufref_ptr(type2ref);
|
||||
size_t type2len = Curl_bufref_len(type2ref);
|
||||
|
||||
#if defined(NTLM_NEEDS_NSS_INIT)
|
||||
/* Make sure the crypto backend is initialized */
|
||||
result = Curl_nss_force_init(data);
|
||||
if(result)
|
||||
return result;
|
||||
#elif defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
#if defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
(void)data;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
struct Curl_easy;
|
||||
|
||||
#if !defined(CURL_DISABLE_CRYPTO_AUTH)
|
||||
#if !defined(CURL_DISABLE_DIGEST_AUTH)
|
||||
struct digestdata;
|
||||
#endif
|
||||
|
||||
@@ -86,7 +86,7 @@ CURLcode Curl_auth_create_login_message(const char *value,
|
||||
CURLcode Curl_auth_create_external_message(const char *user,
|
||||
struct bufref *out);
|
||||
|
||||
#if !defined(CURL_DISABLE_CRYPTO_AUTH)
|
||||
#ifndef CURL_DISABLE_DIGEST_AUTH
|
||||
/* This is used to generate a CRAM-MD5 response message */
|
||||
CURLcode Curl_auth_create_cram_md5_message(const struct bufref *chlg,
|
||||
const char *userp,
|
||||
@@ -119,7 +119,7 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
|
||||
|
||||
/* This is used to clean up the digest specific data */
|
||||
void Curl_auth_digest_cleanup(struct digestdata *digest);
|
||||
#endif /* !CURL_DISABLE_CRYPTO_AUTH */
|
||||
#endif /* !CURL_DISABLE_DIGEST_AUTH */
|
||||
|
||||
#ifdef USE_GSASL
|
||||
/* This is used to evaluate if MECH is supported by gsasl */
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#include "timeval.h"
|
||||
#include "multiif.h"
|
||||
#include "sendf.h"
|
||||
#include "curl_log.h"
|
||||
#include "curl_trc.h"
|
||||
#include "cfilters.h"
|
||||
#include "cf-socket.h"
|
||||
#include "connect.h"
|
||||
@@ -173,7 +173,7 @@ static CURLcode h3_data_setup(struct Curl_cfilter *cf,
|
||||
msh3_lock_initialize(&stream->recv_lock);
|
||||
Curl_bufq_init2(&stream->recvbuf, H3_STREAM_CHUNK_SIZE,
|
||||
H3_STREAM_RECV_CHUNKS, BUFQ_OPT_SOFT_LIMIT);
|
||||
DEBUGF(LOG_CF(data, cf, "data setup"));
|
||||
CURL_TRC_CF(data, cf, "data setup");
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
@@ -183,7 +183,7 @@ static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
|
||||
(void)cf;
|
||||
if(stream) {
|
||||
DEBUGF(LOG_CF(data, cf, "easy handle is done"));
|
||||
CURL_TRC_CF(data, cf, "easy handle is done");
|
||||
Curl_bufq_free(&stream->recvbuf);
|
||||
free(stream);
|
||||
H3_STREAM_LCTX(data) = NULL;
|
||||
@@ -235,7 +235,7 @@ static void MSH3_CALL msh3_conn_connected(MSH3_CONNECTION *Connection,
|
||||
struct Curl_easy *data = CF_DATA_CURRENT(cf);
|
||||
(void)Connection;
|
||||
|
||||
DEBUGF(LOG_CF(data, cf, "[MSH3] connected"));
|
||||
CURL_TRC_CF(data, cf, "[MSH3] connected");
|
||||
ctx->handshake_succeeded = true;
|
||||
ctx->connected = true;
|
||||
ctx->handshake_complete = true;
|
||||
@@ -249,7 +249,7 @@ static void MSH3_CALL msh3_conn_shutdown_complete(MSH3_CONNECTION *Connection,
|
||||
struct Curl_easy *data = CF_DATA_CURRENT(cf);
|
||||
|
||||
(void)Connection;
|
||||
DEBUGF(LOG_CF(data, cf, "[MSH3] shutdown complete"));
|
||||
CURL_TRC_CF(data, cf, "[MSH3] shutdown complete");
|
||||
ctx->connected = false;
|
||||
ctx->handshake_complete = true;
|
||||
}
|
||||
@@ -474,18 +474,18 @@ static ssize_t recv_closed_stream(struct Curl_cfilter *cf,
|
||||
if(stream->reset) {
|
||||
failf(data, "HTTP/3 stream reset by server");
|
||||
*err = CURLE_PARTIAL_FILE;
|
||||
DEBUGF(LOG_CF(data, cf, "cf_recv, was reset -> %d", *err));
|
||||
CURL_TRC_CF(data, cf, "cf_recv, was reset -> %d", *err);
|
||||
goto out;
|
||||
}
|
||||
else if(stream->error3) {
|
||||
failf(data, "HTTP/3 stream was not closed cleanly: (error %zd)",
|
||||
(ssize_t)stream->error3);
|
||||
*err = CURLE_HTTP3;
|
||||
DEBUGF(LOG_CF(data, cf, "cf_recv, closed uncleanly -> %d", *err));
|
||||
CURL_TRC_CF(data, cf, "cf_recv, closed uncleanly -> %d", *err);
|
||||
goto out;
|
||||
}
|
||||
else {
|
||||
DEBUGF(LOG_CF(data, cf, "cf_recv, closed ok -> %d", *err));
|
||||
CURL_TRC_CF(data, cf, "cf_recv, closed ok -> %d", *err);
|
||||
}
|
||||
*err = CURLE_OK;
|
||||
nread = 0;
|
||||
@@ -523,7 +523,7 @@ static ssize_t cf_msh3_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
return -1;
|
||||
}
|
||||
CF_DATA_SAVE(save, cf, data);
|
||||
DEBUGF(LOG_CF(data, cf, "req: recv with %zu byte buffer", len));
|
||||
CURL_TRC_CF(data, cf, "req: recv with %zu byte buffer", len);
|
||||
|
||||
msh3_lock_acquire(&stream->recv_lock);
|
||||
|
||||
@@ -538,8 +538,8 @@ static ssize_t cf_msh3_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
if(!Curl_bufq_is_empty(&stream->recvbuf)) {
|
||||
nread = Curl_bufq_read(&stream->recvbuf,
|
||||
(unsigned char *)buf, len, err);
|
||||
DEBUGF(LOG_CF(data, cf, "read recvbuf(len=%zu) -> %zd, %d",
|
||||
len, nread, *err));
|
||||
CURL_TRC_CF(data, cf, "read recvbuf(len=%zu) -> %zd, %d",
|
||||
len, nread, *err);
|
||||
if(nread < 0)
|
||||
goto out;
|
||||
if(stream->closed)
|
||||
@@ -550,7 +550,7 @@ static ssize_t cf_msh3_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
goto out;
|
||||
}
|
||||
else {
|
||||
DEBUGF(LOG_CF(data, cf, "req: nothing here, call again"));
|
||||
CURL_TRC_CF(data, cf, "req: nothing here, call again");
|
||||
*err = CURLE_AGAIN;
|
||||
}
|
||||
|
||||
@@ -581,7 +581,7 @@ static ssize_t cf_msh3_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
|
||||
/* Sizes must match for cast below to work" */
|
||||
DEBUGASSERT(stream);
|
||||
DEBUGF(LOG_CF(data, cf, "req: send %zu bytes", len));
|
||||
CURL_TRC_CF(data, cf, "req: send %zu bytes", len);
|
||||
|
||||
if(!stream->req) {
|
||||
/* The first send on the request contains the headers and possibly some
|
||||
@@ -630,7 +630,7 @@ static ssize_t cf_msh3_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
break;
|
||||
}
|
||||
|
||||
DEBUGF(LOG_CF(data, cf, "req: send %zu headers", nheader));
|
||||
CURL_TRC_CF(data, cf, "req: send %zu headers", nheader);
|
||||
stream->req = MsH3RequestOpen(ctx->qconn, &msh3_request_if, data,
|
||||
nva, nheader,
|
||||
eos ? MSH3_REQUEST_FLAG_FIN :
|
||||
@@ -646,7 +646,7 @@ static ssize_t cf_msh3_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
}
|
||||
else {
|
||||
/* request is open */
|
||||
DEBUGF(LOG_CF(data, cf, "req: send %zu body bytes", len));
|
||||
CURL_TRC_CF(data, cf, "req: send %zu body bytes", len);
|
||||
if(len > 0xFFFFFFFF) {
|
||||
len = 0xFFFFFFFF;
|
||||
}
|
||||
@@ -694,7 +694,7 @@ static int cf_msh3_get_select_socks(struct Curl_cfilter *cf,
|
||||
drain_stream(cf, data);
|
||||
}
|
||||
}
|
||||
DEBUGF(LOG_CF(data, cf, "select_sock -> %d", bitmap));
|
||||
CURL_TRC_CF(data, cf, "select_sock -> %d", bitmap);
|
||||
CF_DATA_RESTORE(cf, save);
|
||||
return bitmap;
|
||||
}
|
||||
@@ -711,8 +711,8 @@ static bool cf_msh3_data_pending(struct Curl_cfilter *cf,
|
||||
(void)cf;
|
||||
if(stream && stream->req) {
|
||||
msh3_lock_acquire(&stream->recv_lock);
|
||||
DEBUGF(LOG_CF((struct Curl_easy *)data, cf, "data pending = %zu",
|
||||
Curl_bufq_len(&stream->recvbuf)));
|
||||
CURL_TRC_CF((struct Curl_easy *)data, cf, "data pending = %zu",
|
||||
Curl_bufq_len(&stream->recvbuf));
|
||||
pending = !Curl_bufq_is_empty(&stream->recvbuf);
|
||||
msh3_lock_release(&stream->recv_lock);
|
||||
if(pending)
|
||||
@@ -774,7 +774,7 @@ static CURLcode cf_msh3_data_event(struct Curl_cfilter *cf,
|
||||
h3_data_done(cf, data);
|
||||
break;
|
||||
case CF_CTRL_DATA_DONE_SEND:
|
||||
DEBUGF(LOG_CF(data, cf, "req: send done"));
|
||||
CURL_TRC_CF(data, cf, "req: send done");
|
||||
if(stream) {
|
||||
stream->upload_done = TRUE;
|
||||
if(stream->req) {
|
||||
@@ -787,7 +787,7 @@ static CURLcode cf_msh3_data_event(struct Curl_cfilter *cf,
|
||||
}
|
||||
break;
|
||||
case CF_CTRL_CONN_INFO_UPDATE:
|
||||
DEBUGF(LOG_CF(data, cf, "req: update info"));
|
||||
CURL_TRC_CF(data, cf, "req: update info");
|
||||
cf_msh3_active(cf, data);
|
||||
break;
|
||||
default:
|
||||
@@ -813,17 +813,17 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
|
||||
/* TODO: need a way to provide trust anchors to MSH3 */
|
||||
#ifdef DEBUGBUILD
|
||||
/* we need this for our test cases to run */
|
||||
DEBUGF(LOG_CF(data, cf, "non-standard CA not supported, "
|
||||
"switching off verifypeer in DEBUG mode"));
|
||||
CURL_TRC_CF(data, cf, "non-standard CA not supported, "
|
||||
"switching off verifypeer in DEBUG mode");
|
||||
verify = 0;
|
||||
#else
|
||||
DEBUGF(LOG_CF(data, cf, "non-standard CA not supported, "
|
||||
"attempting with built-in verification"));
|
||||
CURL_TRC_CF(data, cf, "non-standard CA not supported, "
|
||||
"attempting with built-in verification");
|
||||
#endif
|
||||
}
|
||||
|
||||
DEBUGF(LOG_CF(data, cf, "connecting to %s:%d (verify=%d)",
|
||||
cf->conn->host.name, (int)cf->conn->remote_port, verify));
|
||||
CURL_TRC_CF(data, cf, "connecting to %s:%d (verify=%d)",
|
||||
cf->conn->host.name, (int)cf->conn->remote_port, verify);
|
||||
|
||||
ctx->api = MsH3ApiOpen();
|
||||
if(!ctx->api) {
|
||||
@@ -888,7 +888,7 @@ static CURLcode cf_msh3_connect(struct Curl_cfilter *cf,
|
||||
if(ctx->handshake_complete) {
|
||||
ctx->handshake_at = Curl_now();
|
||||
if(ctx->handshake_succeeded) {
|
||||
DEBUGF(LOG_CF(data, cf, "handshake succeeded"));
|
||||
CURL_TRC_CF(data, cf, "handshake succeeded");
|
||||
cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
|
||||
cf->conn->httpversion = 30;
|
||||
cf->conn->bundle->multiuse = BUNDLE_MULTIPLEX;
|
||||
@@ -918,7 +918,7 @@ static void cf_msh3_close(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
CF_DATA_SAVE(save, cf, data);
|
||||
|
||||
if(ctx) {
|
||||
DEBUGF(LOG_CF(data, cf, "destroying"));
|
||||
CURL_TRC_CF(data, cf, "destroying");
|
||||
if(ctx->qconn) {
|
||||
MsH3ConnectionClose(ctx->qconn);
|
||||
ctx->qconn = NULL;
|
||||
@@ -935,13 +935,13 @@ static void cf_msh3_close(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
*/
|
||||
ctx->active = FALSE;
|
||||
if(ctx->sock[SP_LOCAL] == cf->conn->sock[cf->sockindex]) {
|
||||
DEBUGF(LOG_CF(data, cf, "cf_msh3_close(%d) active",
|
||||
(int)ctx->sock[SP_LOCAL]));
|
||||
CURL_TRC_CF(data, cf, "cf_msh3_close(%d) active",
|
||||
(int)ctx->sock[SP_LOCAL]);
|
||||
cf->conn->sock[cf->sockindex] = CURL_SOCKET_BAD;
|
||||
}
|
||||
else {
|
||||
DEBUGF(LOG_CF(data, cf, "cf_socket_close(%d) no longer at "
|
||||
"conn->sock[], discarding", (int)ctx->sock[SP_LOCAL]));
|
||||
CURL_TRC_CF(data, cf, "cf_socket_close(%d) no longer at "
|
||||
"conn->sock[], discarding", (int)ctx->sock[SP_LOCAL]);
|
||||
ctx->sock[SP_LOCAL] = CURL_SOCKET_BAD;
|
||||
}
|
||||
if(cf->sockindex == FIRSTSOCKET)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user