mirror of
https://github.com/reactos/CMake.git
synced 2024-11-24 03:59:58 +00:00
Merge branch 'upstream-curl' into update-curl
* upstream-curl: curl 2020-03-04 (b8d13668)
This commit is contained in:
commit
d61c3bd505
@ -11,13 +11,7 @@ if(CURL_HIDDEN_SYMBOLS)
|
||||
set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
|
||||
set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
|
||||
elseif(CMAKE_COMPILER_IS_GNUCC)
|
||||
if(NOT CMAKE_VERSION VERSION_LESS 2.8.10)
|
||||
set(GCC_VERSION ${CMAKE_C_COMPILER_VERSION})
|
||||
else()
|
||||
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
|
||||
OUTPUT_VARIABLE GCC_VERSION)
|
||||
endif()
|
||||
if(NOT GCC_VERSION VERSION_LESS 3.4)
|
||||
if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4)
|
||||
# note: this is considered buggy prior to 4.0 but the autotools don't care, so let's ignore that fact
|
||||
set(SUPPORTS_SYMBOL_HIDING TRUE)
|
||||
set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
|
||||
@ -29,7 +23,7 @@ if(CURL_HIDDEN_SYMBOLS)
|
||||
set(_CFLAG_SYMBOLS_HIDE "-xldscope=hidden")
|
||||
elseif(CMAKE_C_COMPILER_ID MATCHES "Intel" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 9.0)
|
||||
# note: this should probably just check for version 9.1.045 but I'm not 100% sure
|
||||
# so let's to it the same way autotools do.
|
||||
# so let's do it the same way autotools do.
|
||||
set(SUPPORTS_SYMBOL_HIDING TRUE)
|
||||
set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
|
||||
set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2019, 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
|
||||
@ -125,6 +125,7 @@ int main(void)
|
||||
#if defined(HAVE_GETHOSTBYADDR_R_5) || \
|
||||
defined(HAVE_GETHOSTBYADDR_R_5_REENTRANT)
|
||||
rc = gethostbyaddr_r(address, length, type, &h, &hdata);
|
||||
(void)rc;
|
||||
#elif defined(HAVE_GETHOSTBYADDR_R_7) || \
|
||||
defined(HAVE_GETHOSTBYADDR_R_7_REENTRANT)
|
||||
hp = gethostbyaddr_r(address, length, type, &h, buffer, 8192, &h_errnop);
|
||||
@ -132,6 +133,7 @@ int main(void)
|
||||
#elif defined(HAVE_GETHOSTBYADDR_R_8) || \
|
||||
defined(HAVE_GETHOSTBYADDR_R_8_REENTRANT)
|
||||
rc = gethostbyaddr_r(address, length, type, &h, buffer, 8192, &hp, &h_errnop);
|
||||
(void)rc;
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_GETHOSTBYNAME_R_3) || \
|
||||
|
9
Utilities/cmcurl/CMake/FindBearSSL.cmake
Normal file
9
Utilities/cmcurl/CMake/FindBearSSL.cmake
Normal file
@ -0,0 +1,9 @@
|
||||
find_path(BEARSSL_INCLUDE_DIRS bearssl.h)
|
||||
|
||||
find_library(BEARSSL_LIBRARY bearssl)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(BEARSSL DEFAULT_MSG
|
||||
BEARSSL_INCLUDE_DIRS BEARSSL_LIBRARY)
|
||||
|
||||
mark_as_advanced(BEARSSL_INCLUDE_DIRS BEARSSL_LIBRARY)
|
@ -7,34 +7,16 @@
|
||||
# also defined, but not for general use are
|
||||
# CARES_LIBRARY, where to find the c-ares library.
|
||||
|
||||
find_path(CARES_INCLUDE_DIR ares.h
|
||||
/usr/local/include
|
||||
/usr/include
|
||||
)
|
||||
find_path(CARES_INCLUDE_DIR ares.h)
|
||||
|
||||
set(CARES_NAMES ${CARES_NAMES} cares)
|
||||
find_library(CARES_LIBRARY
|
||||
NAMES ${CARES_NAMES}
|
||||
PATHS /usr/lib /usr/local/lib
|
||||
)
|
||||
|
||||
if(CARES_LIBRARY AND CARES_INCLUDE_DIR)
|
||||
set(CARES_LIBRARIES ${CARES_LIBRARY})
|
||||
set(CARES_FOUND "YES")
|
||||
else()
|
||||
set(CARES_FOUND "NO")
|
||||
endif()
|
||||
|
||||
|
||||
if(CARES_FOUND)
|
||||
if(NOT CARES_FIND_QUIETLY)
|
||||
message(STATUS "Found c-ares: ${CARES_LIBRARIES}")
|
||||
endif()
|
||||
else()
|
||||
if(CARES_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Could not find c-ares library")
|
||||
endif()
|
||||
endif()
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(CARES
|
||||
REQUIRED_VARS CARES_LIBRARY CARES_INCLUDE_DIR)
|
||||
|
||||
mark_as_advanced(
|
||||
CARES_LIBRARY
|
||||
|
@ -62,6 +62,7 @@ if(NOT _GSS_FOUND) #not found by pkg-config. Let's take more traditional approac
|
||||
COMMAND ${_GSS_CONFIGURE_SCRIPT} "--cflags" "gssapi"
|
||||
OUTPUT_VARIABLE _GSS_CFLAGS
|
||||
RESULT_VARIABLE _GSS_CONFIGURE_FAILED
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
message(STATUS "CFLAGS: ${_GSS_CFLAGS}")
|
||||
if(NOT _GSS_CONFIGURE_FAILED) # 0 means success
|
||||
@ -84,6 +85,7 @@ if(NOT _GSS_FOUND) #not found by pkg-config. Let's take more traditional approac
|
||||
COMMAND ${_GSS_CONFIGURE_SCRIPT} "--libs" "gssapi"
|
||||
OUTPUT_VARIABLE _GSS_LIB_FLAGS
|
||||
RESULT_VARIABLE _GSS_CONFIGURE_FAILED
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
message(STATUS "LDFLAGS: ${_GSS_LIB_FLAGS}")
|
||||
|
||||
@ -110,6 +112,7 @@ if(NOT _GSS_FOUND) #not found by pkg-config. Let's take more traditional approac
|
||||
COMMAND ${_GSS_CONFIGURE_SCRIPT} "--version"
|
||||
OUTPUT_VARIABLE _GSS_VERSION
|
||||
RESULT_VARIABLE _GSS_CONFIGURE_FAILED
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
# older versions may not have the "--version" parameter. In this case we just don't care.
|
||||
@ -121,6 +124,7 @@ if(NOT _GSS_FOUND) #not found by pkg-config. Let's take more traditional approac
|
||||
COMMAND ${_GSS_CONFIGURE_SCRIPT} "--vendor"
|
||||
OUTPUT_VARIABLE _GSS_VENDOR
|
||||
RESULT_VARIABLE _GSS_CONFIGURE_FAILED
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
# older versions may not have the "--vendor" parameter. In this case we just don't care.
|
||||
@ -134,7 +138,7 @@ if(NOT _GSS_FOUND) #not found by pkg-config. Let's take more traditional approac
|
||||
endif()
|
||||
endif()
|
||||
|
||||
else() # either there is no config script or we are on platform that doesn't provide one (Windows?)
|
||||
else() # either there is no config script or we are on a platform that doesn't provide one (Windows?)
|
||||
|
||||
find_path(_GSS_INCLUDE_DIR
|
||||
NAMES
|
||||
@ -164,7 +168,7 @@ if(NOT _GSS_FOUND) #not found by pkg-config. Let's take more traditional approac
|
||||
set(CMAKE_REQUIRED_DEFINITIONS "")
|
||||
endif()
|
||||
else()
|
||||
# I'm not convienced if this is the right way but this is what autotools do at the moment
|
||||
# I'm not convinced if this is the right way but this is what autotools do at the moment
|
||||
find_path(_GSS_INCLUDE_DIR
|
||||
NAMES
|
||||
"gssapi.h"
|
||||
|
@ -5,31 +5,18 @@
|
||||
# LIBSSH2_INCLUDE_DIR - the libssh2 include directory
|
||||
# LIBSSH2_LIBRARY - the libssh2 library name
|
||||
|
||||
if(LIBSSH2_INCLUDE_DIR AND LIBSSH2_LIBRARY)
|
||||
set(LibSSH2_FIND_QUIETLY TRUE)
|
||||
endif()
|
||||
find_path(LIBSSH2_INCLUDE_DIR libssh2.h)
|
||||
|
||||
find_path(LIBSSH2_INCLUDE_DIR libssh2.h
|
||||
)
|
||||
|
||||
find_library(LIBSSH2_LIBRARY NAMES ssh2
|
||||
)
|
||||
find_library(LIBSSH2_LIBRARY NAMES ssh2 libssh2)
|
||||
|
||||
if(LIBSSH2_INCLUDE_DIR)
|
||||
file(STRINGS "${LIBSSH2_INCLUDE_DIR}/libssh2.h" libssh2_version_str REGEX "^#define[\t ]+LIBSSH2_VERSION_NUM[\t ]+0x[0-9][0-9][0-9][0-9][0-9][0-9].*")
|
||||
|
||||
string(REGEX REPLACE "^.*LIBSSH2_VERSION_NUM[\t ]+0x([0-9][0-9]).*$" "\\1" LIBSSH2_VERSION_MAJOR "${libssh2_version_str}")
|
||||
string(REGEX REPLACE "^.*LIBSSH2_VERSION_NUM[\t ]+0x[0-9][0-9]([0-9][0-9]).*$" "\\1" LIBSSH2_VERSION_MINOR "${libssh2_version_str}")
|
||||
string(REGEX REPLACE "^.*LIBSSH2_VERSION_NUM[\t ]+0x[0-9][0-9][0-9][0-9]([0-9][0-9]).*$" "\\1" LIBSSH2_VERSION_PATCH "${libssh2_version_str}")
|
||||
|
||||
string(REGEX REPLACE "^0(.+)" "\\1" LIBSSH2_VERSION_MAJOR "${LIBSSH2_VERSION_MAJOR}")
|
||||
string(REGEX REPLACE "^0(.+)" "\\1" LIBSSH2_VERSION_MINOR "${LIBSSH2_VERSION_MINOR}")
|
||||
string(REGEX REPLACE "^0(.+)" "\\1" LIBSSH2_VERSION_PATCH "${LIBSSH2_VERSION_PATCH}")
|
||||
|
||||
set(LIBSSH2_VERSION "${LIBSSH2_VERSION_MAJOR}.${LIBSSH2_VERSION_MINOR}.${LIBSSH2_VERSION_PATCH}")
|
||||
file(STRINGS "${LIBSSH2_INCLUDE_DIR}/libssh2.h" libssh2_version_str REGEX "^#define[\t ]+LIBSSH2_VERSION[\t ]+\"(.*)\"")
|
||||
string(REGEX REPLACE "^.*\"([^\"]+)\"" "\\1" LIBSSH2_VERSION "${libssh2_version_str}")
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(LibSSH2 DEFAULT_MSG LIBSSH2_INCLUDE_DIR LIBSSH2_LIBRARY )
|
||||
find_package_handle_standard_args(LibSSH2
|
||||
REQUIRED_VARS LIBSSH2_LIBRARY LIBSSH2_INCLUDE_DIR
|
||||
VERSION_VAR LIBSSH2_VERSION)
|
||||
|
||||
mark_as_advanced(LIBSSH2_INCLUDE_DIR LIBSSH2_LIBRARY LIBSSH2_VERSION_MAJOR LIBSSH2_VERSION_MINOR LIBSSH2_VERSION_PATCH LIBSSH2_VERSION)
|
||||
mark_as_advanced(LIBSSH2_INCLUDE_DIR LIBSSH2_LIBRARY)
|
||||
|
@ -10,9 +10,9 @@ find_package_handle_standard_args(NGHTTP2
|
||||
REQUIRED_VARS
|
||||
NGHTTP2_LIBRARY
|
||||
NGHTTP2_INCLUDE_DIR
|
||||
FAIL_MESSAGE
|
||||
"Could NOT find NGHTTP2"
|
||||
)
|
||||
|
||||
set(NGHTTP2_INCLUDE_DIRS ${NGHTTP2_INCLUDE_DIR})
|
||||
set(NGHTTP2_LIBRARIES ${NGHTTP2_LIBRARY})
|
||||
|
||||
mark_as_advanced(NGHTTP2_INCLUDE_DIRS NGHTTP2_LIBRARIES)
|
||||
|
17
Utilities/cmcurl/CMake/FindNSS.cmake
Normal file
17
Utilities/cmcurl/CMake/FindNSS.cmake
Normal file
@ -0,0 +1,17 @@
|
||||
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)
|
@ -32,7 +32,7 @@ int main(void) {
|
||||
return 0;
|
||||
}" curl_cv_recv)
|
||||
if(curl_cv_recv)
|
||||
if(NOT DEFINED curl_cv_func_recv_args OR "${curl_cv_func_recv_args}" STREQUAL "unknown")
|
||||
if(NOT DEFINED curl_cv_func_recv_args OR curl_cv_func_recv_args STREQUAL "unknown")
|
||||
foreach(recv_retv "int" "ssize_t" )
|
||||
foreach(recv_arg1 "SOCKET" "int" )
|
||||
foreach(recv_arg2 "char *" "void *" )
|
||||
@ -81,7 +81,7 @@ if(curl_cv_recv)
|
||||
string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,[^,]*,([^,]*)$" "\\1" RECV_TYPE_RETV "${curl_cv_func_recv_args}")
|
||||
endif()
|
||||
|
||||
if("${curl_cv_func_recv_args}" STREQUAL "unknown")
|
||||
if(curl_cv_func_recv_args STREQUAL "unknown")
|
||||
message(FATAL_ERROR "Cannot find proper types to use for recv args")
|
||||
endif()
|
||||
else()
|
||||
|
@ -7,7 +7,6 @@ if(NOT UNIX)
|
||||
set(HAVE_LIBNSL 0)
|
||||
set(HAVE_GETHOSTNAME 1)
|
||||
set(HAVE_LIBZ 0)
|
||||
set(HAVE_LIBCRYPTO 0)
|
||||
|
||||
set(HAVE_DLOPEN 0)
|
||||
|
||||
|
@ -2,12 +2,11 @@
|
||||
|
||||
# Returns a list of arguments that evaluate to true
|
||||
function(count_true output_count_var)
|
||||
set(lst)
|
||||
set(lst_len 0)
|
||||
foreach(option_var IN LISTS ARGN)
|
||||
if(${option_var})
|
||||
list(APPEND lst ${option_var})
|
||||
math(EXPR lst_len "${lst_len} + 1")
|
||||
endif()
|
||||
endforeach()
|
||||
list(LENGTH lst lst_len)
|
||||
set(${output_count_var} ${lst_len} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
@ -91,7 +91,7 @@ endif()
|
||||
# | (__| |_| | _ <| |___
|
||||
# \___|\___/|_| \_\_____|
|
||||
#
|
||||
# Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
# Copyright (C) 1998 - 2020, 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
|
||||
@ -136,7 +136,7 @@ if(0) # This code not needed for building within CMake.
|
||||
message(WARNING "the curl cmake build system is poorly maintained. Be aware")
|
||||
endif()
|
||||
|
||||
file(READ ${CURL_SOURCE_DIR}/include/curl/curlver.h CURL_VERSION_H_CONTENTS)
|
||||
file(STRINGS ${CURL_SOURCE_DIR}/include/curl/curlver.h CURL_VERSION_H_CONTENTS REGEX "#define LIBCURL_VERSION( |_NUM )")
|
||||
string(REGEX MATCH "#define LIBCURL_VERSION \"[^\"]*"
|
||||
CURL_VERSION ${CURL_VERSION_H_CONTENTS})
|
||||
string(REGEX REPLACE "[^\"]+\"" "" CURL_VERSION ${CURL_VERSION})
|
||||
@ -168,7 +168,18 @@ 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)
|
||||
option(ENABLE_INET_PTON "Set to OFF to prevent usage of inet_pton when building against modern SDKs while still requiring compatibility with older Windows versions, such as Windows XP, Windows Server 2003 etc." ON)
|
||||
set(CURL_TARGET_WINDOWS_VERSION "" CACHE STRING "Minimum target Windows version as hex string")
|
||||
if(CURL_TARGET_WINDOWS_VERSION)
|
||||
add_definitions(-D_WIN32_WINNT=${CURL_TARGET_WINDOWS_VERSION})
|
||||
elseif(ENABLE_INET_PTON)
|
||||
# _WIN32_WINNT_VISTA (0x0600)
|
||||
add_definitions(-D_WIN32_WINNT=0x0600)
|
||||
else()
|
||||
# _WIN32_WINNT_WINXP (0x0501)
|
||||
add_definitions(-D_WIN32_WINNT=0x0501)
|
||||
endif()
|
||||
endif()
|
||||
option(CURL_LTO "Turn on compiler Link Time Optimizations" OFF)
|
||||
|
||||
if(0) # This code not needed for building within CMake.
|
||||
cmake_dependent_option(ENABLE_THREADED_RESOLVER "Set to ON to enable threaded DNS lookup"
|
||||
@ -184,8 +195,9 @@ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG)
|
||||
foreach(_CCOPT -pedantic -Wall -W -Wpointer-arith -Wwrite-strings -Wunused -Wshadow -Winline -Wnested-externs -Wmissing-declarations -Wmissing-prototypes -Wno-long-long -Wfloat-equal -Wno-multichar -Wsign-compare -Wundef -Wno-format-nonliteral -Wendif-labels -Wstrict-prototypes -Wdeclaration-after-statement -Wstrict-aliasing=3 -Wcast-align -Wtype-limits -Wold-style-declaration -Wmissing-parameter-type -Wempty-body -Wclobbered -Wignored-qualifiers -Wconversion -Wno-sign-conversion -Wvla -Wdouble-promotion -Wno-system-headers -Wno-pedantic-ms-format)
|
||||
# surprisingly, CHECK_C_COMPILER_FLAG needs a new variable to store each new
|
||||
# test result in.
|
||||
check_c_compiler_flag(${_CCOPT} OPT${_CCOPT})
|
||||
if(OPT${_CCOPT})
|
||||
string(MAKE_C_IDENTIFIER "OPT${_CCOPT}" _optvarname)
|
||||
check_c_compiler_flag(${_CCOPT} ${_optvarname})
|
||||
if(${_optvarname})
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_CCOPT}")
|
||||
endif()
|
||||
endforeach()
|
||||
@ -216,7 +228,6 @@ if(ENABLE_ARES)
|
||||
set(USE_ARES 1)
|
||||
find_package(CARES REQUIRED)
|
||||
list(APPEND CURL_LIBS ${CARES_LIBRARY})
|
||||
set(CURL_LIBS ${CURL_LIBS} ${CARES_LIBRARY})
|
||||
endif()
|
||||
|
||||
if(0) # This code not needed for building within CMake.
|
||||
@ -267,6 +278,7 @@ if(HTTP_ONLY)
|
||||
set(CURL_DISABLE_RTSP ON)
|
||||
set(CURL_DISABLE_POP3 ON)
|
||||
set(CURL_DISABLE_IMAP ON)
|
||||
set(CURL_DISABLE_SMB ON)
|
||||
set(CURL_DISABLE_SMTP ON)
|
||||
set(CURL_DISABLE_GOPHER ON)
|
||||
endif()
|
||||
@ -332,6 +344,7 @@ if(${CMAKE_SYSTEM_NAME} MATCHES AIX)
|
||||
endif()
|
||||
|
||||
# Include all the necessary files for macros
|
||||
include(CMakePushCheckState)
|
||||
include(CheckFunctionExists)
|
||||
include(CheckIncludeFile)
|
||||
include(CheckIncludeFiles)
|
||||
@ -359,7 +372,7 @@ endif()
|
||||
|
||||
# Check for all needed libraries
|
||||
if(0) # This code not needed for building within CMake.
|
||||
check_library_exists_concat("dl" dlopen HAVE_LIBDL)
|
||||
check_library_exists_concat("${CMAKE_DL_LIBS}" dlopen HAVE_LIBDL)
|
||||
else()
|
||||
# Use the cmake-defined dl libs as dl is should not be used
|
||||
# on HPUX, but rather dld this avoids a warning
|
||||
@ -390,7 +403,7 @@ if(WIN32)
|
||||
endif()
|
||||
|
||||
# check SSL libraries
|
||||
# TODO support GNUTLS, NSS, POLARSSL, CYASSL
|
||||
# TODO support GnuTLS and WolfSSL
|
||||
|
||||
if(APPLE)
|
||||
option(CMAKE_USE_SECTRANSP "enable Apple OS native SSL/TLS" OFF)
|
||||
@ -401,9 +414,11 @@ if(WIN32)
|
||||
CMAKE_USE_WINSSL OFF)
|
||||
endif()
|
||||
option(CMAKE_USE_MBEDTLS "Enable mbedTLS for SSL/TLS" OFF)
|
||||
option(CMAKE_USE_BEARSSL "Enable BearSSL for SSL/TLS" OFF)
|
||||
option(CMAKE_USE_NSS "Enable NSS for SSL/TLS" OFF)
|
||||
|
||||
set(openssl_default ON)
|
||||
if(WIN32 OR CMAKE_USE_SECTRANSP OR CMAKE_USE_WINSSL OR CMAKE_USE_MBEDTLS)
|
||||
if(WIN32 OR CMAKE_USE_SECTRANSP OR CMAKE_USE_WINSSL OR CMAKE_USE_MBEDTLS OR CMAKE_USE_NSS)
|
||||
set(openssl_default OFF)
|
||||
endif()
|
||||
|
||||
@ -412,6 +427,8 @@ count_true(enabled_ssl_options_count
|
||||
CMAKE_USE_SECTRANSP
|
||||
CMAKE_USE_OPENSSL
|
||||
CMAKE_USE_MBEDTLS
|
||||
CMAKE_USE_BEARSSL
|
||||
CMAKE_USE_NSS
|
||||
)
|
||||
if(enabled_ssl_options_count GREATER "1")
|
||||
set(CURL_WITH_MULTI_SSL ON)
|
||||
@ -457,8 +474,6 @@ if(CMAKE_USE_OPENSSL)
|
||||
endif()
|
||||
set(SSL_ENABLED ON)
|
||||
set(USE_OPENSSL ON)
|
||||
set(HAVE_LIBCRYPTO ON)
|
||||
set(HAVE_LIBSSL ON)
|
||||
list(APPEND CURL_LIBS ${OPENSSL_LIBRARIES})
|
||||
include_directories(${OPENSSL_INCLUDE_DIR})
|
||||
|
||||
@ -492,6 +507,27 @@ if(CMAKE_USE_MBEDTLS)
|
||||
include_directories(${MBEDTLS_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
if(CMAKE_USE_BEARSSL)
|
||||
find_package(BearSSL REQUIRED)
|
||||
set(SSL_ENABLED ON)
|
||||
set(USE_BEARSSL ON)
|
||||
list(APPEND CURL_LIBS ${BEARSSL_LIBRARY})
|
||||
include_directories(${BEARSSL_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
if(CMAKE_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)
|
||||
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()
|
||||
|
||||
option(USE_NGHTTP2 "Use Nghttp2 library" OFF)
|
||||
if(USE_NGHTTP2)
|
||||
find_package(NGHTTP2 REQUIRED)
|
||||
@ -499,6 +535,10 @@ if(USE_NGHTTP2)
|
||||
list(APPEND CURL_LIBS ${NGHTTP2_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
set(USE_WIN32_CRYPTO ON)
|
||||
endif()
|
||||
|
||||
if(NOT CURL_DISABLE_LDAP)
|
||||
if(WIN32)
|
||||
option(USE_WIN32_LDAP "Use Windows LDAP implementation" ON)
|
||||
@ -653,7 +693,7 @@ endif()
|
||||
option(CURL_BROTLI "Set to ON to enable building curl with brotli support." OFF)
|
||||
set(HAVE_BROTLI OFF)
|
||||
if(CURL_BROTLI)
|
||||
find_package(BROTLI QUIET)
|
||||
find_package(Brotli QUIET)
|
||||
if(BROTLI_FOUND)
|
||||
set(HAVE_BROTLI ON)
|
||||
list(APPEND CURL_LIBS ${BROTLI_LIBRARIES})
|
||||
@ -793,7 +833,9 @@ elseif("${CURL_CA_PATH}" STREQUAL "none")
|
||||
unset(CURL_CA_PATH CACHE)
|
||||
elseif("${CURL_CA_PATH}" STREQUAL "auto")
|
||||
unset(CURL_CA_PATH CACHE)
|
||||
set(CURL_CA_PATH_AUTODETECT TRUE)
|
||||
if(NOT USE_NSS)
|
||||
set(CURL_CA_PATH_AUTODETECT TRUE)
|
||||
endif()
|
||||
else()
|
||||
set(CURL_CA_PATH_SET TRUE)
|
||||
endif()
|
||||
@ -983,6 +1025,7 @@ check_symbol_exists(strlcat "${CURL_INCLUDES}" HAVE_STRLCAT)
|
||||
check_symbol_exists(getpwuid "${CURL_INCLUDES}" HAVE_GETPWUID)
|
||||
check_symbol_exists(getpwuid_r "${CURL_INCLUDES}" HAVE_GETPWUID_R)
|
||||
check_symbol_exists(geteuid "${CURL_INCLUDES}" HAVE_GETEUID)
|
||||
check_symbol_exists(usleep "${CURL_INCLUDES}" HAVE_USLEEP)
|
||||
check_symbol_exists(utime "${CURL_INCLUDES}" HAVE_UTIME)
|
||||
check_symbol_exists(gmtime_r "${CURL_INCLUDES}" HAVE_GMTIME_R)
|
||||
check_symbol_exists(localtime_r "${CURL_INCLUDES}" HAVE_LOCALTIME_R)
|
||||
@ -1010,6 +1053,7 @@ check_symbol_exists(ftruncate "${CURL_INCLUDES}" HAVE_FTRUNCATE)
|
||||
check_symbol_exists(getprotobyname "${CURL_INCLUDES}" HAVE_GETPROTOBYNAME)
|
||||
check_symbol_exists(getpeername "${CURL_INCLUDES}" HAVE_GETPEERNAME)
|
||||
check_symbol_exists(getsockname "${CURL_INCLUDES}" HAVE_GETSOCKNAME)
|
||||
check_symbol_exists(if_nametoindex "${CURL_INCLUDES}" HAVE_IF_NAMETOINDEX)
|
||||
check_symbol_exists(getrlimit "${CURL_INCLUDES}" HAVE_GETRLIMIT)
|
||||
check_symbol_exists(setlocale "${CURL_INCLUDES}" HAVE_SETLOCALE)
|
||||
check_symbol_exists(setmode "${CURL_INCLUDES}" HAVE_SETMODE)
|
||||
@ -1018,20 +1062,7 @@ check_symbol_exists(fcntl "${CURL_INCLUDES}" HAVE_FCNTL)
|
||||
check_symbol_exists(ioctl "${CURL_INCLUDES}" HAVE_IOCTL)
|
||||
check_symbol_exists(setsockopt "${CURL_INCLUDES}" HAVE_SETSOCKOPT)
|
||||
check_function_exists(mach_absolute_time HAVE_MACH_ABSOLUTE_TIME)
|
||||
|
||||
# symbol exists in win32, but function does not.
|
||||
if(WIN32)
|
||||
if(ENABLE_INET_PTON)
|
||||
check_function_exists(inet_pton HAVE_INET_PTON)
|
||||
# _WIN32_WINNT_VISTA (0x0600)
|
||||
add_definitions(-D_WIN32_WINNT=0x0600)
|
||||
else()
|
||||
# _WIN32_WINNT_WINXP (0x0501)
|
||||
add_definitions(-D_WIN32_WINNT=0x0501)
|
||||
endif()
|
||||
else()
|
||||
check_function_exists(inet_pton HAVE_INET_PTON)
|
||||
endif()
|
||||
check_symbol_exists(inet_pton "${CURL_INCLUDES}" HAVE_INET_PTON)
|
||||
|
||||
check_symbol_exists(fsetxattr "${CURL_INCLUDES}" HAVE_FSETXATTR)
|
||||
if(HAVE_FSETXATTR)
|
||||
@ -1255,6 +1286,23 @@ if(CURL_WERROR)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CURL_LTO)
|
||||
if(CMAKE_VERSION VERSION_LESS 3.9)
|
||||
message(FATAL_ERROR "Requested LTO but your cmake version ${CMAKE_VERSION} is to old. You need at least 3.9")
|
||||
endif()
|
||||
|
||||
cmake_policy(SET CMP0069 NEW)
|
||||
|
||||
include(CheckIPOSupported)
|
||||
check_ipo_supported(RESULT CURL_HAS_LTO OUTPUT CURL_LTO_ERROR LANGUAGES C)
|
||||
if(CURL_HAS_LTO)
|
||||
message(STATUS "LTO supported and enabled")
|
||||
else()
|
||||
message(FATAL_ERROR "LTO was requested - but compiler doesn't support it\n${CURL_LTO_ERROR}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
# Ugly (but functional) way to include "Makefile.inc" by transforming it (= regenerate it).
|
||||
function(transform_makefile_inc INPUT_FILE OUTPUT_FILE)
|
||||
file(READ ${INPUT_FILE} MAKEFILE_INC_TEXT)
|
||||
@ -1309,14 +1357,22 @@ if(BUILD_TESTING)
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
|
||||
# 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 AND (USE_OPENSSL OR USE_WINDOWS_SSPI OR USE_DARWINSSL OR USE_MBEDTLS OR USE_WIN32_CRYPTO))
|
||||
set(use_ntlm ON)
|
||||
else()
|
||||
set(use_ntlm OFF)
|
||||
endif()
|
||||
|
||||
# Helper to populate a list (_items) with a label when conditions (the remaining
|
||||
# args) are satisfied
|
||||
function(_add_if label)
|
||||
# TODO need to disable policy CMP0054 (CMake 3.1) to allow this indirection
|
||||
macro(_add_if label)
|
||||
# needs to be a macro to allow this indirection
|
||||
if(${ARGN})
|
||||
set(_items ${_items} "${label}" PARENT_SCOPE)
|
||||
set(_items ${_items} "${label}")
|
||||
endif()
|
||||
endfunction()
|
||||
endmacro()
|
||||
|
||||
# Clear list and try to detect available features
|
||||
set(_items)
|
||||
@ -1338,15 +1394,14 @@ _add_if("Kerberos" NOT CURL_DISABLE_CRYPTO_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
|
||||
if(NOT CURL_DISABLE_CRYPTO_AUTH AND (USE_OPENSSL OR USE_WINDOWS_SSPI OR USE_SECTRANSP OR USE_MBEDTLS))
|
||||
_add_if("NTLM" 1)
|
||||
# TODO missing option (autoconf: --enable-ntlm-wb)
|
||||
_add_if("NTLM_WB" NOT CURL_DISABLE_HTTP AND NTLM_WB_ENABLED)
|
||||
endif()
|
||||
_add_if("NTLM" use_ntlm)
|
||||
# TODO missing option (autoconf: --enable-ntlm-wb)
|
||||
_add_if("NTLM_WB" use_ntlm AND NOT CURL_DISABLE_HTTP AND NTLM_WB_ENABLED)
|
||||
# TODO missing option (--enable-tls-srp), depends on GNUTLS_SRP/OPENSSL_SRP
|
||||
_add_if("TLS-SRP" USE_TLS_SRP)
|
||||
# TODO option --with-nghttp2 tests for nghttp2 lib and nghttp2/nghttp2.h header
|
||||
_add_if("HTTP2" USE_NGHTTP2)
|
||||
_add_if("HTTPS-proxy" SSL_ENABLED AND (USE_OPENSSL OR USE_GNUTLS OR USE_NSS))
|
||||
string(REPLACE ";" " " SUPPORT_FEATURES "${_items}")
|
||||
message(STATUS "Enabled features: ${SUPPORT_FEATURES}")
|
||||
|
||||
@ -1371,6 +1426,8 @@ _add_if("POP3" NOT CURL_DISABLE_POP3)
|
||||
_add_if("POP3S" NOT CURL_DISABLE_POP3 AND SSL_ENABLED)
|
||||
_add_if("IMAP" NOT CURL_DISABLE_IMAP)
|
||||
_add_if("IMAPS" NOT CURL_DISABLE_IMAP AND SSL_ENABLED)
|
||||
_add_if("SMB" NOT CURL_DISABLE_SMB AND use_ntlm)
|
||||
_add_if("SMBS" NOT CURL_DISABLE_SMB AND SSL_ENABLED AND use_ntlm)
|
||||
_add_if("SMTP" NOT CURL_DISABLE_SMTP)
|
||||
_add_if("SMTPS" NOT CURL_DISABLE_SMTP AND SSL_ENABLED)
|
||||
_add_if("SCP" USE_LIBSSH2)
|
||||
@ -1389,6 +1446,8 @@ _add_if("WinSSL" SSL_ENABLED AND USE_WINDOWS_SSPI)
|
||||
_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)
|
||||
if(_items)
|
||||
list(SORT _items)
|
||||
endif()
|
||||
|
@ -1,6 +1,6 @@
|
||||
COPYRIGHT AND PERMISSION NOTICE
|
||||
|
||||
Copyright (c) 1996 - 2019, Daniel Stenberg, <daniel@haxx.se>, and many
|
||||
Copyright (c) 1996 - 2020, Daniel Stenberg, <daniel@haxx.se>, and many
|
||||
contributors, see the THANKS file.
|
||||
|
||||
All rights reserved.
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
#ifndef __CURL_CURLVER_H
|
||||
#define __CURL_CURLVER_H
|
||||
#ifndef CURLINC_CURLVER_H
|
||||
#define CURLINC_CURLVER_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2020, 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
|
||||
@ -26,16 +26,16 @@
|
||||
a script at release-time. This was made its own header file in 7.11.2 */
|
||||
|
||||
/* This is the global package copyright */
|
||||
#define LIBCURL_COPYRIGHT "1996 - 2019 Daniel Stenberg, <daniel@haxx.se>."
|
||||
#define LIBCURL_COPYRIGHT "1996 - 2020 Daniel Stenberg, <daniel@haxx.se>."
|
||||
|
||||
/* This is the version number of the libcurl package from which this header
|
||||
file origins: */
|
||||
#define LIBCURL_VERSION "7.65.0"
|
||||
#define LIBCURL_VERSION "7.69.0"
|
||||
|
||||
/* The numeric version number is also available "in parts" by using these
|
||||
defines: */
|
||||
#define LIBCURL_VERSION_MAJOR 7
|
||||
#define LIBCURL_VERSION_MINOR 65
|
||||
#define LIBCURL_VERSION_MINOR 69
|
||||
#define LIBCURL_VERSION_PATCH 0
|
||||
|
||||
/* This is the numeric version of the libcurl version number, meant for easier
|
||||
@ -57,7 +57,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 0x074100
|
||||
#define LIBCURL_VERSION_NUM 0x074500
|
||||
|
||||
/*
|
||||
* This is the date and time when the full source package was created. The
|
||||
@ -74,4 +74,4 @@
|
||||
#define CURL_AT_LEAST_VERSION(x,y,z) \
|
||||
(LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z))
|
||||
|
||||
#endif /* __CURL_CURLVER_H */
|
||||
#endif /* CURLINC_CURLVER_H */
|
||||
|
@ -1,5 +1,5 @@
|
||||
#ifndef __CURL_EASY_H
|
||||
#define __CURL_EASY_H
|
||||
#ifndef CURLINC_EASY_H
|
||||
#define CURLINC_EASY_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2019, 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
#ifndef __CURL_MPRINTF_H
|
||||
#define __CURL_MPRINTF_H
|
||||
#ifndef CURLINC_MPRINTF_H
|
||||
#define CURLINC_MPRINTF_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2019, 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
|
||||
@ -47,4 +47,4 @@ CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __CURL_MPRINTF_H */
|
||||
#endif /* CURLINC_MPRINTF_H */
|
||||
|
@ -1,5 +1,5 @@
|
||||
#ifndef __CURL_MULTI_H
|
||||
#define __CURL_MULTI_H
|
||||
#ifndef CURLINC_MULTI_H
|
||||
#define CURLINC_MULTI_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2020, 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
|
||||
@ -72,6 +72,8 @@ typedef enum {
|
||||
attempted to get added - again */
|
||||
CURLM_RECURSIVE_API_CALL, /* an api function was called from inside a
|
||||
callback */
|
||||
CURLM_WAKEUP_FAILURE, /* wakeup is unavailable or failed */
|
||||
CURLM_BAD_FUNCTION_ARGUMENT, /* function called with a bad parameter */
|
||||
CURLM_LAST
|
||||
} CURLMcode;
|
||||
|
||||
@ -173,6 +175,29 @@ CURL_EXTERN CURLMcode curl_multi_wait(CURLM *multi_handle,
|
||||
int timeout_ms,
|
||||
int *ret);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_poll()
|
||||
*
|
||||
* Desc: Poll on all fds within a CURLM set as well as any
|
||||
* additional fds passed to the function.
|
||||
*
|
||||
* Returns: CURLMcode type, general multi error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_poll(CURLM *multi_handle,
|
||||
struct curl_waitfd extra_fds[],
|
||||
unsigned int extra_nfds,
|
||||
int timeout_ms,
|
||||
int *ret);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_wakeup()
|
||||
*
|
||||
* Desc: wakes up a sleeping curl_multi_poll call.
|
||||
*
|
||||
* Returns: CURLMcode type, general multi error code.
|
||||
*/
|
||||
CURL_EXTERN CURLMcode curl_multi_wakeup(CURLM *multi_handle);
|
||||
|
||||
/*
|
||||
* Name: curl_multi_perform()
|
||||
*
|
||||
@ -319,68 +344,58 @@ CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle,
|
||||
CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle,
|
||||
long *milliseconds);
|
||||
|
||||
#undef CINIT /* re-using the same name as in curl.h */
|
||||
|
||||
#ifdef CURL_ISOCPP
|
||||
#define CINIT(name,type,num) CURLMOPT_ ## name = CURLOPTTYPE_ ## type + num
|
||||
#else
|
||||
/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
|
||||
#define LONG CURLOPTTYPE_LONG
|
||||
#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT
|
||||
#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT
|
||||
#define OFF_T CURLOPTTYPE_OFF_T
|
||||
#define CINIT(name,type,number) CURLMOPT_/**/name = type + number
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
/* This is the socket callback function pointer */
|
||||
CINIT(SOCKETFUNCTION, FUNCTIONPOINT, 1),
|
||||
CURLOPT(CURLMOPT_SOCKETFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 1),
|
||||
|
||||
/* This is the argument passed to the socket callback */
|
||||
CINIT(SOCKETDATA, OBJECTPOINT, 2),
|
||||
CURLOPT(CURLMOPT_SOCKETDATA, CURLOPTTYPE_OBJECTPOINT, 2),
|
||||
|
||||
/* set to 1 to enable pipelining for this multi handle */
|
||||
CINIT(PIPELINING, LONG, 3),
|
||||
CURLOPT(CURLMOPT_PIPELINING, CURLOPTTYPE_LONG, 3),
|
||||
|
||||
/* This is the timer callback function pointer */
|
||||
CINIT(TIMERFUNCTION, FUNCTIONPOINT, 4),
|
||||
CURLOPT(CURLMOPT_TIMERFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 4),
|
||||
|
||||
/* This is the argument passed to the timer callback */
|
||||
CINIT(TIMERDATA, OBJECTPOINT, 5),
|
||||
CURLOPT(CURLMOPT_TIMERDATA, CURLOPTTYPE_OBJECTPOINT, 5),
|
||||
|
||||
/* maximum number of entries in the connection cache */
|
||||
CINIT(MAXCONNECTS, LONG, 6),
|
||||
CURLOPT(CURLMOPT_MAXCONNECTS, CURLOPTTYPE_LONG, 6),
|
||||
|
||||
/* maximum number of (pipelining) connections to one host */
|
||||
CINIT(MAX_HOST_CONNECTIONS, LONG, 7),
|
||||
CURLOPT(CURLMOPT_MAX_HOST_CONNECTIONS, CURLOPTTYPE_LONG, 7),
|
||||
|
||||
/* maximum number of requests in a pipeline */
|
||||
CINIT(MAX_PIPELINE_LENGTH, LONG, 8),
|
||||
CURLOPT(CURLMOPT_MAX_PIPELINE_LENGTH, CURLOPTTYPE_LONG, 8),
|
||||
|
||||
/* a connection with a content-length longer than this
|
||||
will not be considered for pipelining */
|
||||
CINIT(CONTENT_LENGTH_PENALTY_SIZE, OFF_T, 9),
|
||||
CURLOPT(CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE, CURLOPTTYPE_OFF_T, 9),
|
||||
|
||||
/* a connection with a chunk length longer than this
|
||||
will not be considered for pipelining */
|
||||
CINIT(CHUNK_LENGTH_PENALTY_SIZE, OFF_T, 10),
|
||||
CURLOPT(CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE, CURLOPTTYPE_OFF_T, 10),
|
||||
|
||||
/* a list of site names(+port) that are blacklisted from
|
||||
pipelining */
|
||||
CINIT(PIPELINING_SITE_BL, OBJECTPOINT, 11),
|
||||
CURLOPT(CURLMOPT_PIPELINING_SITE_BL, CURLOPTTYPE_OBJECTPOINT, 11),
|
||||
|
||||
/* a list of server types that are blacklisted from
|
||||
pipelining */
|
||||
CINIT(PIPELINING_SERVER_BL, OBJECTPOINT, 12),
|
||||
CURLOPT(CURLMOPT_PIPELINING_SERVER_BL, CURLOPTTYPE_OBJECTPOINT, 12),
|
||||
|
||||
/* maximum number of open connections in total */
|
||||
CINIT(MAX_TOTAL_CONNECTIONS, LONG, 13),
|
||||
CURLOPT(CURLMOPT_MAX_TOTAL_CONNECTIONS, CURLOPTTYPE_LONG, 13),
|
||||
|
||||
/* This is the server push callback function pointer */
|
||||
CINIT(PUSHFUNCTION, FUNCTIONPOINT, 14),
|
||||
CURLOPT(CURLMOPT_PUSHFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 14),
|
||||
|
||||
/* This is the argument passed to the server push callback */
|
||||
CINIT(PUSHDATA, OBJECTPOINT, 15),
|
||||
CURLOPT(CURLMOPT_PUSHDATA, CURLOPTTYPE_OBJECTPOINT, 15),
|
||||
|
||||
/* maximum number of concurrent streams to support on a connection */
|
||||
CURLOPT(CURLMOPT_MAX_CONCURRENT_STREAMS, CURLOPTTYPE_LONG, 16),
|
||||
|
||||
CURLMOPT_LASTENTRY /* the last unused */
|
||||
} CURLMoption;
|
||||
|
@ -1,5 +1,5 @@
|
||||
#ifndef __STDC_HEADERS_H
|
||||
#define __STDC_HEADERS_H
|
||||
#ifndef CURLINC_STDCHEADERS_H
|
||||
#define CURLINC_STDCHEADERS_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2019, 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
|
||||
@ -30,4 +30,4 @@ size_t fwrite(const void *, size_t, size_t, FILE *);
|
||||
int strcasecmp(const char *, const char *);
|
||||
int strncasecmp(const char *, const char *, size_t);
|
||||
|
||||
#endif /* __STDC_HEADERS_H */
|
||||
#endif /* CURLINC_STDCHEADERS_H */
|
||||
|
@ -1,5 +1,5 @@
|
||||
#ifndef __CURL_SYSTEM_H
|
||||
#define __CURL_SYSTEM_H
|
||||
#ifndef CURLINC_SYSTEM_H
|
||||
#define CURLINC_SYSTEM_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2019, 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
|
||||
@ -137,15 +137,26 @@
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
|
||||
#elif defined(__LCC__)
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
# if defined(__e2k__) /* MCST eLbrus C Compiler */
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
|
||||
# define CURL_PULL_SYS_TYPES_H 1
|
||||
# define CURL_PULL_SYS_SOCKET_H 1
|
||||
# else /* Local (or Little) C Compiler */
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
# define CURL_FORMAT_CURL_OFF_T "ld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "lu"
|
||||
# define CURL_SUFFIX_CURL_OFF_T L
|
||||
# define CURL_SUFFIX_CURL_OFF_TU UL
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
# endif
|
||||
|
||||
#elif defined(__SYMBIAN32__)
|
||||
# if defined(__EABI__) /* Treat all ARM compilers equally */
|
||||
# if defined(__EABI__) /* Treat all ARM compilers equally */
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
@ -288,7 +299,6 @@
|
||||
# define CURL_TYPEOF_CURL_SOCKLEN_T int
|
||||
|
||||
#elif defined(__TINYC__) /* also known as tcc */
|
||||
|
||||
# define CURL_TYPEOF_CURL_OFF_T long long
|
||||
# define CURL_FORMAT_CURL_OFF_T "lld"
|
||||
# define CURL_FORMAT_CURL_OFF_TU "llu"
|
||||
@ -377,6 +387,7 @@
|
||||
# define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
# elif defined(__LP64__) || \
|
||||
defined(__x86_64__) || defined(__ppc64__) || defined(__sparc64__) || \
|
||||
defined(__e2k__) || \
|
||||
(defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 8) || \
|
||||
(defined(__LONG_MAX__) && __LONG_MAX__ == 9223372036854775807L)
|
||||
# define CURL_TYPEOF_CURL_OFF_T long
|
||||
@ -473,21 +484,21 @@
|
||||
*/
|
||||
|
||||
#if defined(__BORLANDC__) && (__BORLANDC__ == 0x0551)
|
||||
# define __CURL_OFF_T_C_HLPR2(x) x
|
||||
# define __CURL_OFF_T_C_HLPR1(x) __CURL_OFF_T_C_HLPR2(x)
|
||||
# define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \
|
||||
__CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_T)
|
||||
# define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \
|
||||
__CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_TU)
|
||||
# define CURLINC_OFF_T_C_HLPR2(x) x
|
||||
# define CURLINC_OFF_T_C_HLPR1(x) CURLINC_OFF_T_C_HLPR2(x)
|
||||
# define CURL_OFF_T_C(Val) CURLINC_OFF_T_C_HLPR1(Val) ## \
|
||||
CURLINC_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_T)
|
||||
# define CURL_OFF_TU_C(Val) CURLINC_OFF_T_C_HLPR1(Val) ## \
|
||||
CURLINC_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_TU)
|
||||
#else
|
||||
# ifdef CURL_ISOCPP
|
||||
# define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val ## Suffix
|
||||
# define CURLINC_OFF_T_C_HLPR2(Val,Suffix) Val ## Suffix
|
||||
# else
|
||||
# define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val/**/Suffix
|
||||
# define CURLINC_OFF_T_C_HLPR2(Val,Suffix) Val/**/Suffix
|
||||
# endif
|
||||
# define __CURL_OFF_T_C_HLPR1(Val,Suffix) __CURL_OFF_T_C_HLPR2(Val,Suffix)
|
||||
# define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_T)
|
||||
# define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_TU)
|
||||
# define CURLINC_OFF_T_C_HLPR1(Val,Suffix) CURLINC_OFF_T_C_HLPR2(Val,Suffix)
|
||||
# define CURL_OFF_T_C(Val) CURLINC_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_T)
|
||||
# define CURL_OFF_TU_C(Val) CURLINC_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_TU)
|
||||
#endif
|
||||
|
||||
#endif /* __CURL_SYSTEM_H */
|
||||
#endif /* CURLINC_SYSTEM_H */
|
||||
|
@ -1,5 +1,5 @@
|
||||
#ifndef __CURL_TYPECHECK_GCC_H
|
||||
#define __CURL_TYPECHECK_GCC_H
|
||||
#ifndef CURLINC_TYPECHECK_GCC_H
|
||||
#define CURLINC_TYPECHECK_GCC_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
@ -25,10 +25,10 @@
|
||||
/* wraps curl_easy_setopt() with typechecking */
|
||||
|
||||
/* To add a new kind of warning, add an
|
||||
* if(_curl_is_sometype_option(_curl_opt))
|
||||
* if(!_curl_is_sometype(value))
|
||||
* if(curlcheck_sometype_option(_curl_opt))
|
||||
* if(!curlcheck_sometype(value))
|
||||
* _curl_easy_setopt_err_sometype();
|
||||
* block and define _curl_is_sometype_option, _curl_is_sometype and
|
||||
* block and define curlcheck_sometype_option, curlcheck_sometype and
|
||||
* _curl_easy_setopt_err_sometype below
|
||||
*
|
||||
* NOTE: We use two nested 'if' statements here instead of the && operator, in
|
||||
@ -38,112 +38,112 @@
|
||||
* To add an option that uses the same type as an existing option, you'll just
|
||||
* need to extend the appropriate _curl_*_option macro
|
||||
*/
|
||||
#define curl_easy_setopt(handle, option, value) \
|
||||
__extension__ ({ \
|
||||
__typeof__(option) _curl_opt = option; \
|
||||
if(__builtin_constant_p(_curl_opt)) { \
|
||||
if(_curl_is_long_option(_curl_opt)) \
|
||||
if(!_curl_is_long(value)) \
|
||||
_curl_easy_setopt_err_long(); \
|
||||
if(_curl_is_off_t_option(_curl_opt)) \
|
||||
if(!_curl_is_off_t(value)) \
|
||||
_curl_easy_setopt_err_curl_off_t(); \
|
||||
if(_curl_is_string_option(_curl_opt)) \
|
||||
if(!_curl_is_string(value)) \
|
||||
_curl_easy_setopt_err_string(); \
|
||||
if(_curl_is_write_cb_option(_curl_opt)) \
|
||||
if(!_curl_is_write_cb(value)) \
|
||||
_curl_easy_setopt_err_write_callback(); \
|
||||
if((_curl_opt) == CURLOPT_RESOLVER_START_FUNCTION) \
|
||||
if(!_curl_is_resolver_start_callback(value)) \
|
||||
_curl_easy_setopt_err_resolver_start_callback(); \
|
||||
if((_curl_opt) == CURLOPT_READFUNCTION) \
|
||||
if(!_curl_is_read_cb(value)) \
|
||||
_curl_easy_setopt_err_read_cb(); \
|
||||
if((_curl_opt) == CURLOPT_IOCTLFUNCTION) \
|
||||
if(!_curl_is_ioctl_cb(value)) \
|
||||
_curl_easy_setopt_err_ioctl_cb(); \
|
||||
if((_curl_opt) == CURLOPT_SOCKOPTFUNCTION) \
|
||||
if(!_curl_is_sockopt_cb(value)) \
|
||||
_curl_easy_setopt_err_sockopt_cb(); \
|
||||
if((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION) \
|
||||
if(!_curl_is_opensocket_cb(value)) \
|
||||
_curl_easy_setopt_err_opensocket_cb(); \
|
||||
if((_curl_opt) == CURLOPT_PROGRESSFUNCTION) \
|
||||
if(!_curl_is_progress_cb(value)) \
|
||||
_curl_easy_setopt_err_progress_cb(); \
|
||||
if((_curl_opt) == CURLOPT_DEBUGFUNCTION) \
|
||||
if(!_curl_is_debug_cb(value)) \
|
||||
_curl_easy_setopt_err_debug_cb(); \
|
||||
if((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION) \
|
||||
if(!_curl_is_ssl_ctx_cb(value)) \
|
||||
_curl_easy_setopt_err_ssl_ctx_cb(); \
|
||||
if(_curl_is_conv_cb_option(_curl_opt)) \
|
||||
if(!_curl_is_conv_cb(value)) \
|
||||
_curl_easy_setopt_err_conv_cb(); \
|
||||
if((_curl_opt) == CURLOPT_SEEKFUNCTION) \
|
||||
if(!_curl_is_seek_cb(value)) \
|
||||
_curl_easy_setopt_err_seek_cb(); \
|
||||
if(_curl_is_cb_data_option(_curl_opt)) \
|
||||
if(!_curl_is_cb_data(value)) \
|
||||
_curl_easy_setopt_err_cb_data(); \
|
||||
if((_curl_opt) == CURLOPT_ERRORBUFFER) \
|
||||
if(!_curl_is_error_buffer(value)) \
|
||||
_curl_easy_setopt_err_error_buffer(); \
|
||||
if((_curl_opt) == CURLOPT_STDERR) \
|
||||
if(!_curl_is_FILE(value)) \
|
||||
_curl_easy_setopt_err_FILE(); \
|
||||
if(_curl_is_postfields_option(_curl_opt)) \
|
||||
if(!_curl_is_postfields(value)) \
|
||||
_curl_easy_setopt_err_postfields(); \
|
||||
if((_curl_opt) == CURLOPT_HTTPPOST) \
|
||||
if(!_curl_is_arr((value), struct curl_httppost)) \
|
||||
_curl_easy_setopt_err_curl_httpost(); \
|
||||
if((_curl_opt) == CURLOPT_MIMEPOST) \
|
||||
if(!_curl_is_ptr((value), curl_mime)) \
|
||||
_curl_easy_setopt_err_curl_mimepost(); \
|
||||
if(_curl_is_slist_option(_curl_opt)) \
|
||||
if(!_curl_is_arr((value), struct curl_slist)) \
|
||||
_curl_easy_setopt_err_curl_slist(); \
|
||||
if((_curl_opt) == CURLOPT_SHARE) \
|
||||
if(!_curl_is_ptr((value), CURLSH)) \
|
||||
_curl_easy_setopt_err_CURLSH(); \
|
||||
} \
|
||||
curl_easy_setopt(handle, _curl_opt, value); \
|
||||
})
|
||||
#define curl_easy_setopt(handle, option, value) \
|
||||
__extension__({ \
|
||||
__typeof__(option) _curl_opt = option; \
|
||||
if(__builtin_constant_p(_curl_opt)) { \
|
||||
if(curlcheck_long_option(_curl_opt)) \
|
||||
if(!curlcheck_long(value)) \
|
||||
_curl_easy_setopt_err_long(); \
|
||||
if(curlcheck_off_t_option(_curl_opt)) \
|
||||
if(!curlcheck_off_t(value)) \
|
||||
_curl_easy_setopt_err_curl_off_t(); \
|
||||
if(curlcheck_string_option(_curl_opt)) \
|
||||
if(!curlcheck_string(value)) \
|
||||
_curl_easy_setopt_err_string(); \
|
||||
if(curlcheck_write_cb_option(_curl_opt)) \
|
||||
if(!curlcheck_write_cb(value)) \
|
||||
_curl_easy_setopt_err_write_callback(); \
|
||||
if((_curl_opt) == CURLOPT_RESOLVER_START_FUNCTION) \
|
||||
if(!curlcheck_resolver_start_callback(value)) \
|
||||
_curl_easy_setopt_err_resolver_start_callback(); \
|
||||
if((_curl_opt) == CURLOPT_READFUNCTION) \
|
||||
if(!curlcheck_read_cb(value)) \
|
||||
_curl_easy_setopt_err_read_cb(); \
|
||||
if((_curl_opt) == CURLOPT_IOCTLFUNCTION) \
|
||||
if(!curlcheck_ioctl_cb(value)) \
|
||||
_curl_easy_setopt_err_ioctl_cb(); \
|
||||
if((_curl_opt) == CURLOPT_SOCKOPTFUNCTION) \
|
||||
if(!curlcheck_sockopt_cb(value)) \
|
||||
_curl_easy_setopt_err_sockopt_cb(); \
|
||||
if((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION) \
|
||||
if(!curlcheck_opensocket_cb(value)) \
|
||||
_curl_easy_setopt_err_opensocket_cb(); \
|
||||
if((_curl_opt) == CURLOPT_PROGRESSFUNCTION) \
|
||||
if(!curlcheck_progress_cb(value)) \
|
||||
_curl_easy_setopt_err_progress_cb(); \
|
||||
if((_curl_opt) == CURLOPT_DEBUGFUNCTION) \
|
||||
if(!curlcheck_debug_cb(value)) \
|
||||
_curl_easy_setopt_err_debug_cb(); \
|
||||
if((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION) \
|
||||
if(!curlcheck_ssl_ctx_cb(value)) \
|
||||
_curl_easy_setopt_err_ssl_ctx_cb(); \
|
||||
if(curlcheck_conv_cb_option(_curl_opt)) \
|
||||
if(!curlcheck_conv_cb(value)) \
|
||||
_curl_easy_setopt_err_conv_cb(); \
|
||||
if((_curl_opt) == CURLOPT_SEEKFUNCTION) \
|
||||
if(!curlcheck_seek_cb(value)) \
|
||||
_curl_easy_setopt_err_seek_cb(); \
|
||||
if(curlcheck_cb_data_option(_curl_opt)) \
|
||||
if(!curlcheck_cb_data(value)) \
|
||||
_curl_easy_setopt_err_cb_data(); \
|
||||
if((_curl_opt) == CURLOPT_ERRORBUFFER) \
|
||||
if(!curlcheck_error_buffer(value)) \
|
||||
_curl_easy_setopt_err_error_buffer(); \
|
||||
if((_curl_opt) == CURLOPT_STDERR) \
|
||||
if(!curlcheck_FILE(value)) \
|
||||
_curl_easy_setopt_err_FILE(); \
|
||||
if(curlcheck_postfields_option(_curl_opt)) \
|
||||
if(!curlcheck_postfields(value)) \
|
||||
_curl_easy_setopt_err_postfields(); \
|
||||
if((_curl_opt) == CURLOPT_HTTPPOST) \
|
||||
if(!curlcheck_arr((value), struct curl_httppost)) \
|
||||
_curl_easy_setopt_err_curl_httpost(); \
|
||||
if((_curl_opt) == CURLOPT_MIMEPOST) \
|
||||
if(!curlcheck_ptr((value), curl_mime)) \
|
||||
_curl_easy_setopt_err_curl_mimepost(); \
|
||||
if(curlcheck_slist_option(_curl_opt)) \
|
||||
if(!curlcheck_arr((value), struct curl_slist)) \
|
||||
_curl_easy_setopt_err_curl_slist(); \
|
||||
if((_curl_opt) == CURLOPT_SHARE) \
|
||||
if(!curlcheck_ptr((value), CURLSH)) \
|
||||
_curl_easy_setopt_err_CURLSH(); \
|
||||
} \
|
||||
curl_easy_setopt(handle, _curl_opt, value); \
|
||||
})
|
||||
|
||||
/* wraps curl_easy_getinfo() with typechecking */
|
||||
#define curl_easy_getinfo(handle, info, arg) \
|
||||
__extension__ ({ \
|
||||
__typeof__(info) _curl_info = info; \
|
||||
if(__builtin_constant_p(_curl_info)) { \
|
||||
if(_curl_is_string_info(_curl_info)) \
|
||||
if(!_curl_is_arr((arg), char *)) \
|
||||
_curl_easy_getinfo_err_string(); \
|
||||
if(_curl_is_long_info(_curl_info)) \
|
||||
if(!_curl_is_arr((arg), long)) \
|
||||
_curl_easy_getinfo_err_long(); \
|
||||
if(_curl_is_double_info(_curl_info)) \
|
||||
if(!_curl_is_arr((arg), double)) \
|
||||
_curl_easy_getinfo_err_double(); \
|
||||
if(_curl_is_slist_info(_curl_info)) \
|
||||
if(!_curl_is_arr((arg), struct curl_slist *)) \
|
||||
_curl_easy_getinfo_err_curl_slist(); \
|
||||
if(_curl_is_tlssessioninfo_info(_curl_info)) \
|
||||
if(!_curl_is_arr((arg), struct curl_tlssessioninfo *)) \
|
||||
_curl_easy_getinfo_err_curl_tlssesssioninfo(); \
|
||||
if(_curl_is_certinfo_info(_curl_info)) \
|
||||
if(!_curl_is_arr((arg), struct curl_certinfo *)) \
|
||||
_curl_easy_getinfo_err_curl_certinfo(); \
|
||||
if(_curl_is_socket_info(_curl_info)) \
|
||||
if(!_curl_is_arr((arg), curl_socket_t)) \
|
||||
_curl_easy_getinfo_err_curl_socket(); \
|
||||
if(_curl_is_off_t_info(_curl_info)) \
|
||||
if(!_curl_is_arr((arg), curl_off_t)) \
|
||||
_curl_easy_getinfo_err_curl_off_t(); \
|
||||
} \
|
||||
curl_easy_getinfo(handle, _curl_info, arg); \
|
||||
})
|
||||
#define curl_easy_getinfo(handle, info, arg) \
|
||||
__extension__({ \
|
||||
__typeof__(info) _curl_info = info; \
|
||||
if(__builtin_constant_p(_curl_info)) { \
|
||||
if(curlcheck_string_info(_curl_info)) \
|
||||
if(!curlcheck_arr((arg), char *)) \
|
||||
_curl_easy_getinfo_err_string(); \
|
||||
if(curlcheck_long_info(_curl_info)) \
|
||||
if(!curlcheck_arr((arg), long)) \
|
||||
_curl_easy_getinfo_err_long(); \
|
||||
if(curlcheck_double_info(_curl_info)) \
|
||||
if(!curlcheck_arr((arg), double)) \
|
||||
_curl_easy_getinfo_err_double(); \
|
||||
if(curlcheck_slist_info(_curl_info)) \
|
||||
if(!curlcheck_arr((arg), struct curl_slist *)) \
|
||||
_curl_easy_getinfo_err_curl_slist(); \
|
||||
if(curlcheck_tlssessioninfo_info(_curl_info)) \
|
||||
if(!curlcheck_arr((arg), struct curl_tlssessioninfo *)) \
|
||||
_curl_easy_getinfo_err_curl_tlssesssioninfo(); \
|
||||
if(curlcheck_certinfo_info(_curl_info)) \
|
||||
if(!curlcheck_arr((arg), struct curl_certinfo *)) \
|
||||
_curl_easy_getinfo_err_curl_certinfo(); \
|
||||
if(curlcheck_socket_info(_curl_info)) \
|
||||
if(!curlcheck_arr((arg), curl_socket_t)) \
|
||||
_curl_easy_getinfo_err_curl_socket(); \
|
||||
if(curlcheck_off_t_info(_curl_info)) \
|
||||
if(!curlcheck_arr((arg), curl_off_t)) \
|
||||
_curl_easy_getinfo_err_curl_off_t(); \
|
||||
} \
|
||||
curl_easy_getinfo(handle, _curl_info, arg); \
|
||||
})
|
||||
|
||||
/*
|
||||
* For now, just make sure that the functions are called with three arguments
|
||||
@ -156,83 +156,83 @@ __extension__ ({ \
|
||||
* functions */
|
||||
|
||||
/* To define a new warning, use _CURL_WARNING(identifier, "message") */
|
||||
#define _CURL_WARNING(id, message) \
|
||||
static void __attribute__((__warning__(message))) \
|
||||
__attribute__((__unused__)) __attribute__((__noinline__)) \
|
||||
#define CURLWARNING(id, message) \
|
||||
static void __attribute__((__warning__(message))) \
|
||||
__attribute__((__unused__)) __attribute__((__noinline__)) \
|
||||
id(void) { __asm__(""); }
|
||||
|
||||
_CURL_WARNING(_curl_easy_setopt_err_long,
|
||||
CURLWARNING(_curl_easy_setopt_err_long,
|
||||
"curl_easy_setopt expects a long argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_curl_off_t,
|
||||
CURLWARNING(_curl_easy_setopt_err_curl_off_t,
|
||||
"curl_easy_setopt expects a curl_off_t argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_string,
|
||||
CURLWARNING(_curl_easy_setopt_err_string,
|
||||
"curl_easy_setopt expects a "
|
||||
"string ('char *' or char[]) argument for this option"
|
||||
)
|
||||
_CURL_WARNING(_curl_easy_setopt_err_write_callback,
|
||||
CURLWARNING(_curl_easy_setopt_err_write_callback,
|
||||
"curl_easy_setopt expects a curl_write_callback argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_resolver_start_callback,
|
||||
CURLWARNING(_curl_easy_setopt_err_resolver_start_callback,
|
||||
"curl_easy_setopt expects a "
|
||||
"curl_resolver_start_callback argument for this option"
|
||||
)
|
||||
_CURL_WARNING(_curl_easy_setopt_err_read_cb,
|
||||
CURLWARNING(_curl_easy_setopt_err_read_cb,
|
||||
"curl_easy_setopt expects a curl_read_callback argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_ioctl_cb,
|
||||
CURLWARNING(_curl_easy_setopt_err_ioctl_cb,
|
||||
"curl_easy_setopt expects a curl_ioctl_callback argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_sockopt_cb,
|
||||
CURLWARNING(_curl_easy_setopt_err_sockopt_cb,
|
||||
"curl_easy_setopt expects a curl_sockopt_callback argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_opensocket_cb,
|
||||
CURLWARNING(_curl_easy_setopt_err_opensocket_cb,
|
||||
"curl_easy_setopt expects a "
|
||||
"curl_opensocket_callback argument for this option"
|
||||
)
|
||||
_CURL_WARNING(_curl_easy_setopt_err_progress_cb,
|
||||
CURLWARNING(_curl_easy_setopt_err_progress_cb,
|
||||
"curl_easy_setopt expects a curl_progress_callback argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_debug_cb,
|
||||
CURLWARNING(_curl_easy_setopt_err_debug_cb,
|
||||
"curl_easy_setopt expects a curl_debug_callback argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_ssl_ctx_cb,
|
||||
CURLWARNING(_curl_easy_setopt_err_ssl_ctx_cb,
|
||||
"curl_easy_setopt expects a curl_ssl_ctx_callback argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_conv_cb,
|
||||
CURLWARNING(_curl_easy_setopt_err_conv_cb,
|
||||
"curl_easy_setopt expects a curl_conv_callback argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_seek_cb,
|
||||
CURLWARNING(_curl_easy_setopt_err_seek_cb,
|
||||
"curl_easy_setopt expects a curl_seek_callback argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_cb_data,
|
||||
CURLWARNING(_curl_easy_setopt_err_cb_data,
|
||||
"curl_easy_setopt expects a "
|
||||
"private data pointer as argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_error_buffer,
|
||||
CURLWARNING(_curl_easy_setopt_err_error_buffer,
|
||||
"curl_easy_setopt expects a "
|
||||
"char buffer of CURL_ERROR_SIZE as argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_FILE,
|
||||
CURLWARNING(_curl_easy_setopt_err_FILE,
|
||||
"curl_easy_setopt expects a 'FILE *' argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_postfields,
|
||||
CURLWARNING(_curl_easy_setopt_err_postfields,
|
||||
"curl_easy_setopt expects a 'void *' or 'char *' argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_curl_httpost,
|
||||
CURLWARNING(_curl_easy_setopt_err_curl_httpost,
|
||||
"curl_easy_setopt expects a 'struct curl_httppost *' "
|
||||
"argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_curl_mimepost,
|
||||
CURLWARNING(_curl_easy_setopt_err_curl_mimepost,
|
||||
"curl_easy_setopt expects a 'curl_mime *' "
|
||||
"argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_curl_slist,
|
||||
CURLWARNING(_curl_easy_setopt_err_curl_slist,
|
||||
"curl_easy_setopt expects a 'struct curl_slist *' argument for this option")
|
||||
_CURL_WARNING(_curl_easy_setopt_err_CURLSH,
|
||||
CURLWARNING(_curl_easy_setopt_err_CURLSH,
|
||||
"curl_easy_setopt expects a CURLSH* argument for this option")
|
||||
|
||||
_CURL_WARNING(_curl_easy_getinfo_err_string,
|
||||
CURLWARNING(_curl_easy_getinfo_err_string,
|
||||
"curl_easy_getinfo expects a pointer to 'char *' for this info")
|
||||
_CURL_WARNING(_curl_easy_getinfo_err_long,
|
||||
CURLWARNING(_curl_easy_getinfo_err_long,
|
||||
"curl_easy_getinfo expects a pointer to long for this info")
|
||||
_CURL_WARNING(_curl_easy_getinfo_err_double,
|
||||
CURLWARNING(_curl_easy_getinfo_err_double,
|
||||
"curl_easy_getinfo expects a pointer to double for this info")
|
||||
_CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
|
||||
CURLWARNING(_curl_easy_getinfo_err_curl_slist,
|
||||
"curl_easy_getinfo expects a pointer to 'struct curl_slist *' for this info")
|
||||
_CURL_WARNING(_curl_easy_getinfo_err_curl_tlssesssioninfo,
|
||||
CURLWARNING(_curl_easy_getinfo_err_curl_tlssesssioninfo,
|
||||
"curl_easy_getinfo expects a pointer to "
|
||||
"'struct curl_tlssessioninfo *' for this info")
|
||||
_CURL_WARNING(_curl_easy_getinfo_err_curl_certinfo,
|
||||
CURLWARNING(_curl_easy_getinfo_err_curl_certinfo,
|
||||
"curl_easy_getinfo expects a pointer to "
|
||||
"'struct curl_certinfo *' for this info")
|
||||
_CURL_WARNING(_curl_easy_getinfo_err_curl_socket,
|
||||
CURLWARNING(_curl_easy_getinfo_err_curl_socket,
|
||||
"curl_easy_getinfo expects a pointer to curl_socket_t for this info")
|
||||
_CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
|
||||
CURLWARNING(_curl_easy_getinfo_err_curl_off_t,
|
||||
"curl_easy_getinfo expects a pointer to curl_off_t for this info")
|
||||
|
||||
/* groups of curl_easy_setops options that take the same type of argument */
|
||||
@ -244,14 +244,14 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
|
||||
*/
|
||||
|
||||
/* evaluates to true if option takes a long argument */
|
||||
#define _curl_is_long_option(option) \
|
||||
#define curlcheck_long_option(option) \
|
||||
(0 < (option) && (option) < CURLOPTTYPE_OBJECTPOINT)
|
||||
|
||||
#define _curl_is_off_t_option(option) \
|
||||
#define curlcheck_off_t_option(option) \
|
||||
((option) > CURLOPTTYPE_OFF_T)
|
||||
|
||||
/* evaluates to true if option takes a char* argument */
|
||||
#define _curl_is_string_option(option) \
|
||||
#define curlcheck_string_option(option) \
|
||||
((option) == CURLOPT_ABSTRACT_UNIX_SOCKET || \
|
||||
(option) == CURLOPT_ACCEPT_ENCODING || \
|
||||
(option) == CURLOPT_ALTSVC || \
|
||||
@ -300,15 +300,18 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
|
||||
(option) == CURLOPT_PROXY_SSLKEY || \
|
||||
(option) == CURLOPT_PROXY_SSLKEYTYPE || \
|
||||
(option) == CURLOPT_PROXY_SSL_CIPHER_LIST || \
|
||||
(option) == CURLOPT_PROXY_TLS13_CIPHERS || \
|
||||
(option) == CURLOPT_PROXY_TLSAUTH_PASSWORD || \
|
||||
(option) == CURLOPT_PROXY_TLSAUTH_USERNAME || \
|
||||
(option) == CURLOPT_PROXY_TLSAUTH_TYPE || \
|
||||
(option) == CURLOPT_PROXY_TLSAUTH_USERNAME || \
|
||||
(option) == CURLOPT_RANDOM_FILE || \
|
||||
(option) == CURLOPT_RANGE || \
|
||||
(option) == CURLOPT_REFERER || \
|
||||
(option) == CURLOPT_REQUEST_TARGET || \
|
||||
(option) == CURLOPT_RTSP_SESSION_ID || \
|
||||
(option) == CURLOPT_RTSP_STREAM_URI || \
|
||||
(option) == CURLOPT_RTSP_TRANSPORT || \
|
||||
(option) == CURLOPT_SASL_AUTHZID || \
|
||||
(option) == CURLOPT_SERVICE_NAME || \
|
||||
(option) == CURLOPT_SOCKS5_GSSAPI_SERVICE || \
|
||||
(option) == CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 || \
|
||||
@ -321,6 +324,7 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
|
||||
(option) == CURLOPT_SSLKEY || \
|
||||
(option) == CURLOPT_SSLKEYTYPE || \
|
||||
(option) == CURLOPT_SSL_CIPHER_LIST || \
|
||||
(option) == CURLOPT_TLS13_CIPHERS || \
|
||||
(option) == CURLOPT_TLSAUTH_PASSWORD || \
|
||||
(option) == CURLOPT_TLSAUTH_TYPE || \
|
||||
(option) == CURLOPT_TLSAUTH_USERNAME || \
|
||||
@ -333,18 +337,18 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
|
||||
0)
|
||||
|
||||
/* evaluates to true if option takes a curl_write_callback argument */
|
||||
#define _curl_is_write_cb_option(option) \
|
||||
((option) == CURLOPT_HEADERFUNCTION || \
|
||||
#define curlcheck_write_cb_option(option) \
|
||||
((option) == CURLOPT_HEADERFUNCTION || \
|
||||
(option) == CURLOPT_WRITEFUNCTION)
|
||||
|
||||
/* evaluates to true if option takes a curl_conv_callback argument */
|
||||
#define _curl_is_conv_cb_option(option) \
|
||||
((option) == CURLOPT_CONV_TO_NETWORK_FUNCTION || \
|
||||
(option) == CURLOPT_CONV_FROM_NETWORK_FUNCTION || \
|
||||
#define curlcheck_conv_cb_option(option) \
|
||||
((option) == CURLOPT_CONV_TO_NETWORK_FUNCTION || \
|
||||
(option) == CURLOPT_CONV_FROM_NETWORK_FUNCTION || \
|
||||
(option) == CURLOPT_CONV_FROM_UTF8_FUNCTION)
|
||||
|
||||
/* evaluates to true if option takes a data argument to pass to a callback */
|
||||
#define _curl_is_cb_data_option(option) \
|
||||
#define curlcheck_cb_data_option(option) \
|
||||
((option) == CURLOPT_CHUNK_DATA || \
|
||||
(option) == CURLOPT_CLOSESOCKETDATA || \
|
||||
(option) == CURLOPT_DEBUGDATA || \
|
||||
@ -362,17 +366,17 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
|
||||
(option) == CURLOPT_SSL_CTX_DATA || \
|
||||
(option) == CURLOPT_WRITEDATA || \
|
||||
(option) == CURLOPT_RESOLVER_START_DATA || \
|
||||
(option) == CURLOPT_CURLU || \
|
||||
(option) == CURLOPT_TRAILERDATA || \
|
||||
0)
|
||||
|
||||
/* evaluates to true if option takes a POST data argument (void* or char*) */
|
||||
#define _curl_is_postfields_option(option) \
|
||||
#define curlcheck_postfields_option(option) \
|
||||
((option) == CURLOPT_POSTFIELDS || \
|
||||
(option) == CURLOPT_COPYPOSTFIELDS || \
|
||||
0)
|
||||
|
||||
/* evaluates to true if option takes a struct curl_slist * argument */
|
||||
#define _curl_is_slist_option(option) \
|
||||
#define curlcheck_slist_option(option) \
|
||||
((option) == CURLOPT_HTTP200ALIASES || \
|
||||
(option) == CURLOPT_HTTPHEADER || \
|
||||
(option) == CURLOPT_MAIL_RCPT || \
|
||||
@ -382,45 +386,46 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
|
||||
(option) == CURLOPT_QUOTE || \
|
||||
(option) == CURLOPT_RESOLVE || \
|
||||
(option) == CURLOPT_TELNETOPTIONS || \
|
||||
(option) == CURLOPT_CONNECT_TO || \
|
||||
0)
|
||||
|
||||
/* groups of curl_easy_getinfo infos that take the same type of argument */
|
||||
|
||||
/* evaluates to true if info expects a pointer to char * argument */
|
||||
#define _curl_is_string_info(info) \
|
||||
#define curlcheck_string_info(info) \
|
||||
(CURLINFO_STRING < (info) && (info) < CURLINFO_LONG)
|
||||
|
||||
/* evaluates to true if info expects a pointer to long argument */
|
||||
#define _curl_is_long_info(info) \
|
||||
#define curlcheck_long_info(info) \
|
||||
(CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE)
|
||||
|
||||
/* evaluates to true if info expects a pointer to double argument */
|
||||
#define _curl_is_double_info(info) \
|
||||
#define curlcheck_double_info(info) \
|
||||
(CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST)
|
||||
|
||||
/* true if info expects a pointer to struct curl_slist * argument */
|
||||
#define _curl_is_slist_info(info) \
|
||||
#define curlcheck_slist_info(info) \
|
||||
(((info) == CURLINFO_SSL_ENGINES) || ((info) == CURLINFO_COOKIELIST))
|
||||
|
||||
/* true if info expects a pointer to struct curl_tlssessioninfo * argument */
|
||||
#define _curl_is_tlssessioninfo_info(info) \
|
||||
#define curlcheck_tlssessioninfo_info(info) \
|
||||
(((info) == CURLINFO_TLS_SSL_PTR) || ((info) == CURLINFO_TLS_SESSION))
|
||||
|
||||
/* true if info expects a pointer to struct curl_certinfo * argument */
|
||||
#define _curl_is_certinfo_info(info) ((info) == CURLINFO_CERTINFO)
|
||||
#define curlcheck_certinfo_info(info) ((info) == CURLINFO_CERTINFO)
|
||||
|
||||
/* true if info expects a pointer to struct curl_socket_t argument */
|
||||
#define _curl_is_socket_info(info) \
|
||||
#define curlcheck_socket_info(info) \
|
||||
(CURLINFO_SOCKET < (info) && (info) < CURLINFO_OFF_T)
|
||||
|
||||
/* true if info expects a pointer to curl_off_t argument */
|
||||
#define _curl_is_off_t_info(info) \
|
||||
#define curlcheck_off_t_info(info) \
|
||||
(CURLINFO_OFF_T < (info))
|
||||
|
||||
|
||||
/* typecheck helpers -- check whether given expression has requested type*/
|
||||
|
||||
/* For pointers, you can use the _curl_is_ptr/_curl_is_arr macros,
|
||||
/* For pointers, you can use the curlcheck_ptr/curlcheck_arr macros,
|
||||
* otherwise define a new macro. Search for __builtin_types_compatible_p
|
||||
* in the GCC manual.
|
||||
* NOTE: these macros MUST NOT EVALUATE their arguments! The argument is
|
||||
@ -430,35 +435,35 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
|
||||
*/
|
||||
|
||||
/* XXX: should evaluate to true if expr is a pointer */
|
||||
#define _curl_is_any_ptr(expr) \
|
||||
#define curlcheck_any_ptr(expr) \
|
||||
(sizeof(expr) == sizeof(void *))
|
||||
|
||||
/* evaluates to true if expr is NULL */
|
||||
/* XXX: must not evaluate expr, so this check is not accurate */
|
||||
#define _curl_is_NULL(expr) \
|
||||
#define curlcheck_NULL(expr) \
|
||||
(__builtin_types_compatible_p(__typeof__(expr), __typeof__(NULL)))
|
||||
|
||||
/* evaluates to true if expr is type*, const type* or NULL */
|
||||
#define _curl_is_ptr(expr, type) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), type *) || \
|
||||
#define curlcheck_ptr(expr, type) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), type *) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), const type *))
|
||||
|
||||
/* evaluates to true if expr is one of type[], type*, NULL or const type* */
|
||||
#define _curl_is_arr(expr, type) \
|
||||
(_curl_is_ptr((expr), type) || \
|
||||
#define curlcheck_arr(expr, type) \
|
||||
(curlcheck_ptr((expr), type) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), type []))
|
||||
|
||||
/* evaluates to true if expr is a string */
|
||||
#define _curl_is_string(expr) \
|
||||
(_curl_is_arr((expr), char) || \
|
||||
_curl_is_arr((expr), signed char) || \
|
||||
_curl_is_arr((expr), unsigned char))
|
||||
#define curlcheck_string(expr) \
|
||||
(curlcheck_arr((expr), char) || \
|
||||
curlcheck_arr((expr), signed char) || \
|
||||
curlcheck_arr((expr), unsigned char))
|
||||
|
||||
/* evaluates to true if expr is a long (no matter the signedness)
|
||||
* XXX: for now, int is also accepted (and therefore short and char, which
|
||||
* are promoted to int when passed to a variadic function) */
|
||||
#define _curl_is_long(expr) \
|
||||
#define curlcheck_long(expr) \
|
||||
(__builtin_types_compatible_p(__typeof__(expr), long) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), signed long) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), unsigned long) || \
|
||||
@ -473,59 +478,59 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
|
||||
__builtin_types_compatible_p(__typeof__(expr), unsigned char))
|
||||
|
||||
/* evaluates to true if expr is of type curl_off_t */
|
||||
#define _curl_is_off_t(expr) \
|
||||
#define curlcheck_off_t(expr) \
|
||||
(__builtin_types_compatible_p(__typeof__(expr), curl_off_t))
|
||||
|
||||
/* evaluates to true if expr is abuffer suitable for CURLOPT_ERRORBUFFER */
|
||||
/* XXX: also check size of an char[] array? */
|
||||
#define _curl_is_error_buffer(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), char *) || \
|
||||
#define curlcheck_error_buffer(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), char *) || \
|
||||
__builtin_types_compatible_p(__typeof__(expr), char[]))
|
||||
|
||||
/* evaluates to true if expr is of type (const) void* or (const) FILE* */
|
||||
#if 0
|
||||
#define _curl_is_cb_data(expr) \
|
||||
(_curl_is_ptr((expr), void) || \
|
||||
_curl_is_ptr((expr), FILE))
|
||||
#define curlcheck_cb_data(expr) \
|
||||
(curlcheck_ptr((expr), void) || \
|
||||
curlcheck_ptr((expr), FILE))
|
||||
#else /* be less strict */
|
||||
#define _curl_is_cb_data(expr) \
|
||||
_curl_is_any_ptr(expr)
|
||||
#define curlcheck_cb_data(expr) \
|
||||
curlcheck_any_ptr(expr)
|
||||
#endif
|
||||
|
||||
/* evaluates to true if expr is of type FILE* */
|
||||
#define _curl_is_FILE(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
#define curlcheck_FILE(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
(__builtin_types_compatible_p(__typeof__(expr), FILE *)))
|
||||
|
||||
/* evaluates to true if expr can be passed as POST data (void* or char*) */
|
||||
#define _curl_is_postfields(expr) \
|
||||
(_curl_is_ptr((expr), void) || \
|
||||
_curl_is_arr((expr), char) || \
|
||||
_curl_is_arr((expr), unsigned char))
|
||||
#define curlcheck_postfields(expr) \
|
||||
(curlcheck_ptr((expr), void) || \
|
||||
curlcheck_arr((expr), char) || \
|
||||
curlcheck_arr((expr), unsigned char))
|
||||
|
||||
/* helper: __builtin_types_compatible_p distinguishes between functions and
|
||||
* function pointers, hide it */
|
||||
#define _curl_callback_compatible(func, type) \
|
||||
(__builtin_types_compatible_p(__typeof__(func), type) || \
|
||||
#define curlcheck_cb_compatible(func, type) \
|
||||
(__builtin_types_compatible_p(__typeof__(func), type) || \
|
||||
__builtin_types_compatible_p(__typeof__(func) *, type))
|
||||
|
||||
/* evaluates to true if expr is of type curl_resolver_start_callback */
|
||||
#define _curl_is_resolver_start_callback(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
_curl_callback_compatible((expr), curl_resolver_start_callback))
|
||||
#define curlcheck_resolver_start_callback(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
curlcheck_cb_compatible((expr), curl_resolver_start_callback))
|
||||
|
||||
/* evaluates to true if expr is of type curl_read_callback or "similar" */
|
||||
#define _curl_is_read_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
_curl_callback_compatible((expr), __typeof__(fread) *) || \
|
||||
_curl_callback_compatible((expr), curl_read_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_read_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_read_callback2) || \
|
||||
_curl_callback_compatible((expr), _curl_read_callback3) || \
|
||||
_curl_callback_compatible((expr), _curl_read_callback4) || \
|
||||
_curl_callback_compatible((expr), _curl_read_callback5) || \
|
||||
_curl_callback_compatible((expr), _curl_read_callback6))
|
||||
#define curlcheck_read_cb(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
curlcheck_cb_compatible((expr), __typeof__(fread) *) || \
|
||||
curlcheck_cb_compatible((expr), curl_read_callback) || \
|
||||
curlcheck_cb_compatible((expr), _curl_read_callback1) || \
|
||||
curlcheck_cb_compatible((expr), _curl_read_callback2) || \
|
||||
curlcheck_cb_compatible((expr), _curl_read_callback3) || \
|
||||
curlcheck_cb_compatible((expr), _curl_read_callback4) || \
|
||||
curlcheck_cb_compatible((expr), _curl_read_callback5) || \
|
||||
curlcheck_cb_compatible((expr), _curl_read_callback6))
|
||||
typedef size_t (*_curl_read_callback1)(char *, size_t, size_t, void *);
|
||||
typedef size_t (*_curl_read_callback2)(char *, size_t, size_t, const void *);
|
||||
typedef size_t (*_curl_read_callback3)(char *, size_t, size_t, FILE *);
|
||||
@ -534,16 +539,16 @@ typedef size_t (*_curl_read_callback5)(void *, size_t, size_t, const void *);
|
||||
typedef size_t (*_curl_read_callback6)(void *, size_t, size_t, FILE *);
|
||||
|
||||
/* evaluates to true if expr is of type curl_write_callback or "similar" */
|
||||
#define _curl_is_write_cb(expr) \
|
||||
(_curl_is_read_cb(expr) || \
|
||||
_curl_callback_compatible((expr), __typeof__(fwrite) *) || \
|
||||
_curl_callback_compatible((expr), curl_write_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_write_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_write_callback2) || \
|
||||
_curl_callback_compatible((expr), _curl_write_callback3) || \
|
||||
_curl_callback_compatible((expr), _curl_write_callback4) || \
|
||||
_curl_callback_compatible((expr), _curl_write_callback5) || \
|
||||
_curl_callback_compatible((expr), _curl_write_callback6))
|
||||
#define curlcheck_write_cb(expr) \
|
||||
(curlcheck_read_cb(expr) || \
|
||||
curlcheck_cb_compatible((expr), __typeof__(fwrite) *) || \
|
||||
curlcheck_cb_compatible((expr), curl_write_callback) || \
|
||||
curlcheck_cb_compatible((expr), _curl_write_callback1) || \
|
||||
curlcheck_cb_compatible((expr), _curl_write_callback2) || \
|
||||
curlcheck_cb_compatible((expr), _curl_write_callback3) || \
|
||||
curlcheck_cb_compatible((expr), _curl_write_callback4) || \
|
||||
curlcheck_cb_compatible((expr), _curl_write_callback5) || \
|
||||
curlcheck_cb_compatible((expr), _curl_write_callback6))
|
||||
typedef size_t (*_curl_write_callback1)(const char *, size_t, size_t, void *);
|
||||
typedef size_t (*_curl_write_callback2)(const char *, size_t, size_t,
|
||||
const void *);
|
||||
@ -554,37 +559,37 @@ typedef size_t (*_curl_write_callback5)(const void *, size_t, size_t,
|
||||
typedef size_t (*_curl_write_callback6)(const void *, size_t, size_t, FILE *);
|
||||
|
||||
/* evaluates to true if expr is of type curl_ioctl_callback or "similar" */
|
||||
#define _curl_is_ioctl_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
_curl_callback_compatible((expr), curl_ioctl_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_ioctl_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_ioctl_callback2) || \
|
||||
_curl_callback_compatible((expr), _curl_ioctl_callback3) || \
|
||||
_curl_callback_compatible((expr), _curl_ioctl_callback4))
|
||||
#define curlcheck_ioctl_cb(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
curlcheck_cb_compatible((expr), curl_ioctl_callback) || \
|
||||
curlcheck_cb_compatible((expr), _curl_ioctl_callback1) || \
|
||||
curlcheck_cb_compatible((expr), _curl_ioctl_callback2) || \
|
||||
curlcheck_cb_compatible((expr), _curl_ioctl_callback3) || \
|
||||
curlcheck_cb_compatible((expr), _curl_ioctl_callback4))
|
||||
typedef curlioerr (*_curl_ioctl_callback1)(CURL *, int, void *);
|
||||
typedef curlioerr (*_curl_ioctl_callback2)(CURL *, int, const void *);
|
||||
typedef curlioerr (*_curl_ioctl_callback3)(CURL *, curliocmd, void *);
|
||||
typedef curlioerr (*_curl_ioctl_callback4)(CURL *, curliocmd, const void *);
|
||||
|
||||
/* evaluates to true if expr is of type curl_sockopt_callback or "similar" */
|
||||
#define _curl_is_sockopt_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
_curl_callback_compatible((expr), curl_sockopt_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_sockopt_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_sockopt_callback2))
|
||||
#define curlcheck_sockopt_cb(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
curlcheck_cb_compatible((expr), curl_sockopt_callback) || \
|
||||
curlcheck_cb_compatible((expr), _curl_sockopt_callback1) || \
|
||||
curlcheck_cb_compatible((expr), _curl_sockopt_callback2))
|
||||
typedef int (*_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype);
|
||||
typedef int (*_curl_sockopt_callback2)(const void *, curl_socket_t,
|
||||
curlsocktype);
|
||||
|
||||
/* evaluates to true if expr is of type curl_opensocket_callback or
|
||||
"similar" */
|
||||
#define _curl_is_opensocket_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
_curl_callback_compatible((expr), curl_opensocket_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_opensocket_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_opensocket_callback2) || \
|
||||
_curl_callback_compatible((expr), _curl_opensocket_callback3) || \
|
||||
_curl_callback_compatible((expr), _curl_opensocket_callback4))
|
||||
#define curlcheck_opensocket_cb(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
curlcheck_cb_compatible((expr), curl_opensocket_callback) || \
|
||||
curlcheck_cb_compatible((expr), _curl_opensocket_callback1) || \
|
||||
curlcheck_cb_compatible((expr), _curl_opensocket_callback2) || \
|
||||
curlcheck_cb_compatible((expr), _curl_opensocket_callback3) || \
|
||||
curlcheck_cb_compatible((expr), _curl_opensocket_callback4))
|
||||
typedef curl_socket_t (*_curl_opensocket_callback1)
|
||||
(void *, curlsocktype, struct curl_sockaddr *);
|
||||
typedef curl_socket_t (*_curl_opensocket_callback2)
|
||||
@ -595,28 +600,28 @@ typedef curl_socket_t (*_curl_opensocket_callback4)
|
||||
(const void *, curlsocktype, const struct curl_sockaddr *);
|
||||
|
||||
/* evaluates to true if expr is of type curl_progress_callback or "similar" */
|
||||
#define _curl_is_progress_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
_curl_callback_compatible((expr), curl_progress_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_progress_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_progress_callback2))
|
||||
#define curlcheck_progress_cb(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
curlcheck_cb_compatible((expr), curl_progress_callback) || \
|
||||
curlcheck_cb_compatible((expr), _curl_progress_callback1) || \
|
||||
curlcheck_cb_compatible((expr), _curl_progress_callback2))
|
||||
typedef int (*_curl_progress_callback1)(void *,
|
||||
double, double, double, double);
|
||||
typedef int (*_curl_progress_callback2)(const void *,
|
||||
double, double, double, double);
|
||||
|
||||
/* evaluates to true if expr is of type curl_debug_callback or "similar" */
|
||||
#define _curl_is_debug_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
_curl_callback_compatible((expr), curl_debug_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_debug_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_debug_callback2) || \
|
||||
_curl_callback_compatible((expr), _curl_debug_callback3) || \
|
||||
_curl_callback_compatible((expr), _curl_debug_callback4) || \
|
||||
_curl_callback_compatible((expr), _curl_debug_callback5) || \
|
||||
_curl_callback_compatible((expr), _curl_debug_callback6) || \
|
||||
_curl_callback_compatible((expr), _curl_debug_callback7) || \
|
||||
_curl_callback_compatible((expr), _curl_debug_callback8))
|
||||
#define curlcheck_debug_cb(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
curlcheck_cb_compatible((expr), curl_debug_callback) || \
|
||||
curlcheck_cb_compatible((expr), _curl_debug_callback1) || \
|
||||
curlcheck_cb_compatible((expr), _curl_debug_callback2) || \
|
||||
curlcheck_cb_compatible((expr), _curl_debug_callback3) || \
|
||||
curlcheck_cb_compatible((expr), _curl_debug_callback4) || \
|
||||
curlcheck_cb_compatible((expr), _curl_debug_callback5) || \
|
||||
curlcheck_cb_compatible((expr), _curl_debug_callback6) || \
|
||||
curlcheck_cb_compatible((expr), _curl_debug_callback7) || \
|
||||
curlcheck_cb_compatible((expr), _curl_debug_callback8))
|
||||
typedef int (*_curl_debug_callback1) (CURL *,
|
||||
curl_infotype, char *, size_t, void *);
|
||||
typedef int (*_curl_debug_callback2) (CURL *,
|
||||
@ -636,17 +641,17 @@ typedef int (*_curl_debug_callback8) (CURL *,
|
||||
|
||||
/* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */
|
||||
/* this is getting even messier... */
|
||||
#define _curl_is_ssl_ctx_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
_curl_callback_compatible((expr), curl_ssl_ctx_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_ssl_ctx_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_ssl_ctx_callback2) || \
|
||||
_curl_callback_compatible((expr), _curl_ssl_ctx_callback3) || \
|
||||
_curl_callback_compatible((expr), _curl_ssl_ctx_callback4) || \
|
||||
_curl_callback_compatible((expr), _curl_ssl_ctx_callback5) || \
|
||||
_curl_callback_compatible((expr), _curl_ssl_ctx_callback6) || \
|
||||
_curl_callback_compatible((expr), _curl_ssl_ctx_callback7) || \
|
||||
_curl_callback_compatible((expr), _curl_ssl_ctx_callback8))
|
||||
#define curlcheck_ssl_ctx_cb(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
curlcheck_cb_compatible((expr), curl_ssl_ctx_callback) || \
|
||||
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback1) || \
|
||||
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback2) || \
|
||||
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback3) || \
|
||||
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback4) || \
|
||||
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback5) || \
|
||||
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback6) || \
|
||||
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback7) || \
|
||||
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback8))
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback1)(CURL *, void *, void *);
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback2)(CURL *, void *, const void *);
|
||||
typedef CURLcode (*_curl_ssl_ctx_callback3)(CURL *, const void *, void *);
|
||||
@ -669,26 +674,26 @@ typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback8;
|
||||
#endif
|
||||
|
||||
/* evaluates to true if expr is of type curl_conv_callback or "similar" */
|
||||
#define _curl_is_conv_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
_curl_callback_compatible((expr), curl_conv_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_conv_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_conv_callback2) || \
|
||||
_curl_callback_compatible((expr), _curl_conv_callback3) || \
|
||||
_curl_callback_compatible((expr), _curl_conv_callback4))
|
||||
#define curlcheck_conv_cb(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
curlcheck_cb_compatible((expr), curl_conv_callback) || \
|
||||
curlcheck_cb_compatible((expr), _curl_conv_callback1) || \
|
||||
curlcheck_cb_compatible((expr), _curl_conv_callback2) || \
|
||||
curlcheck_cb_compatible((expr), _curl_conv_callback3) || \
|
||||
curlcheck_cb_compatible((expr), _curl_conv_callback4))
|
||||
typedef CURLcode (*_curl_conv_callback1)(char *, size_t length);
|
||||
typedef CURLcode (*_curl_conv_callback2)(const char *, size_t length);
|
||||
typedef CURLcode (*_curl_conv_callback3)(void *, size_t length);
|
||||
typedef CURLcode (*_curl_conv_callback4)(const void *, size_t length);
|
||||
|
||||
/* evaluates to true if expr is of type curl_seek_callback or "similar" */
|
||||
#define _curl_is_seek_cb(expr) \
|
||||
(_curl_is_NULL(expr) || \
|
||||
_curl_callback_compatible((expr), curl_seek_callback) || \
|
||||
_curl_callback_compatible((expr), _curl_seek_callback1) || \
|
||||
_curl_callback_compatible((expr), _curl_seek_callback2))
|
||||
#define curlcheck_seek_cb(expr) \
|
||||
(curlcheck_NULL(expr) || \
|
||||
curlcheck_cb_compatible((expr), curl_seek_callback) || \
|
||||
curlcheck_cb_compatible((expr), _curl_seek_callback1) || \
|
||||
curlcheck_cb_compatible((expr), _curl_seek_callback2))
|
||||
typedef CURLcode (*_curl_seek_callback1)(void *, curl_off_t, int);
|
||||
typedef CURLcode (*_curl_seek_callback2)(const void *, curl_off_t, int);
|
||||
|
||||
|
||||
#endif /* __CURL_TYPECHECK_GCC_H */
|
||||
#endif /* CURLINC_TYPECHECK_GCC_H */
|
||||
|
@ -1,5 +1,5 @@
|
||||
#ifndef __CURL_URLAPI_H
|
||||
#define __CURL_URLAPI_H
|
||||
#ifndef CURLINC_URLAPI_H
|
||||
#define CURLINC_URLAPI_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
@ -77,6 +77,8 @@ typedef enum {
|
||||
#define CURLU_URLENCODE (1<<7) /* URL encode on set */
|
||||
#define CURLU_APPENDQUERY (1<<8) /* append a form style part */
|
||||
#define CURLU_GUESS_SCHEME (1<<9) /* legacy curl-style guessing */
|
||||
#define CURLU_NO_AUTHORITY (1<<10) /* Allow empty authority when the
|
||||
scheme is unknown. */
|
||||
|
||||
typedef struct Curl_URL CURLU;
|
||||
|
||||
@ -120,4 +122,4 @@ CURL_EXTERN CURLUcode curl_url_set(CURLU *handle, CURLUPart what,
|
||||
} /* end of extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif /* CURLINC_URLAPI_H */
|
||||
|
@ -20,7 +20,6 @@ list(APPEND HHEADERS
|
||||
|
||||
if(MSVC AND NOT CURL_STATICLIB)
|
||||
list(APPEND CSOURCES libcurl.rc)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4127")
|
||||
endif()
|
||||
|
||||
# SET(CSOURCES
|
||||
@ -121,6 +120,12 @@ endif()
|
||||
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)
|
||||
# Add "_imp" as a suffix before the extension to avoid conflicting with the statically linked "libcurl.lib"
|
||||
|
@ -5,7 +5,7 @@
|
||||
# | (__| |_| | _ <| |___
|
||||
# \___|\___/|_| \_\_____|
|
||||
#
|
||||
# Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
# Copyright (C) 1998 - 2020, 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
|
||||
@ -28,14 +28,22 @@ LIB_VAUTH_CFILES = vauth/vauth.c vauth/cleartext.c vauth/cram.c \
|
||||
LIB_VAUTH_HFILES = vauth/vauth.h vauth/digest.h vauth/ntlm.h
|
||||
|
||||
LIB_VTLS_CFILES = vtls/openssl.c vtls/gtls.c vtls/vtls.c vtls/nss.c \
|
||||
vtls/polarssl.c vtls/polarssl_threadlock.c \
|
||||
vtls/cyassl.c vtls/schannel.c vtls/schannel_verify.c \
|
||||
vtls/sectransp.c vtls/gskit.c vtls/mbedtls.c vtls/mesalink.c
|
||||
vtls/mbedtls_threadlock.c vtls/wolfssl.c vtls/schannel.c \
|
||||
vtls/schannel_verify.c vtls/sectransp.c vtls/gskit.c vtls/mbedtls.c \
|
||||
vtls/mesalink.c vtls/bearssl.c
|
||||
|
||||
LIB_VTLS_HFILES = vtls/openssl.h vtls/vtls.h vtls/gtls.h \
|
||||
vtls/nssg.h vtls/polarssl.h vtls/polarssl_threadlock.h \
|
||||
vtls/cyassl.h vtls/schannel.h vtls/sectransp.h vtls/gskit.h \
|
||||
vtls/mbedtls.h vtls/mesalink.h
|
||||
LIB_VTLS_HFILES = vtls/openssl.h vtls/vtls.h vtls/gtls.h vtls/nssg.h \
|
||||
vtls/mbedtls_threadlock.h vtls/wolfssl.h vtls/schannel.h \
|
||||
vtls/sectransp.h vtls/gskit.h vtls/mbedtls.h vtls/mesalink.h \
|
||||
vtls/bearssl.h
|
||||
|
||||
LIB_VQUIC_CFILES = vquic/ngtcp2.c vquic/quiche.c
|
||||
|
||||
LIB_VQUIC_HFILES = vquic/ngtcp2.h vquic/quiche.h
|
||||
|
||||
LIB_VSSH_CFILES = vssh/libssh2.c vssh/libssh.c vssh/wolfssh.c
|
||||
|
||||
LIB_VSSH_HFILES = vssh/ssh.h
|
||||
|
||||
LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
|
||||
cookie.c http.c sendf.c ftp.c url.c dict.c if2ip.c speedcheck.c \
|
||||
@ -46,7 +54,7 @@ LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
|
||||
http_digest.c md4.c md5.c http_negotiate.c inet_pton.c strtoofft.c \
|
||||
strerror.c amigaos.c hostasyn.c hostip4.c hostip6.c hostsyn.c \
|
||||
inet_ntop.c parsedate.c select.c tftp.c splay.c strdup.c socks.c \
|
||||
ssh.c ssh-libssh.c curl_addrinfo.c socks_gssapi.c socks_sspi.c \
|
||||
curl_addrinfo.c socks_gssapi.c socks_sspi.c \
|
||||
curl_sspi.c slist.c nonblock.c curl_memrchr.c imap.c pop3.c smtp.c \
|
||||
pingpong.c rtsp.c curl_threads.c warnless.c hmac.c curl_rtmp.c \
|
||||
openldap.c curl_gethostname.c gopher.c idn_win32.c \
|
||||
@ -55,7 +63,7 @@ LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
|
||||
curl_multibyte.c hostcheck.c conncache.c dotdot.c \
|
||||
x509asn1.c http2.c smb.c curl_endian.c curl_des.c system_win32.c \
|
||||
mime.c sha256.c setopt.c curl_path.c curl_ctype.c curl_range.c psl.c \
|
||||
doh.c urlapi.c curl_get_line.c altsvc.c
|
||||
doh.c urlapi.c curl_get_line.c altsvc.c socketpair.c rename.c
|
||||
|
||||
LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \
|
||||
formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h if2ip.h \
|
||||
@ -66,7 +74,7 @@ LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \
|
||||
http_negotiate.h inet_pton.h amigaos.h strtoofft.h strerror.h \
|
||||
inet_ntop.h curlx.h curl_memory.h curl_setup.h transfer.h select.h \
|
||||
easyif.h multiif.h parsedate.h tftp.h sockaddr.h splay.h strdup.h \
|
||||
socks.h ssh.h curl_base64.h curl_addrinfo.h curl_sspi.h \
|
||||
socks.h curl_base64.h curl_addrinfo.h curl_sspi.h \
|
||||
slist.h nonblock.h curl_memrchr.h imap.h pop3.h smtp.h pingpong.h \
|
||||
rtsp.h curl_threads.h warnless.h curl_hmac.h curl_rtmp.h \
|
||||
curl_gethostname.h gopher.h http_proxy.h non-ascii.h asyn.h \
|
||||
@ -76,9 +84,11 @@ LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \
|
||||
x509asn1.h http2.h sigpipe.h smb.h curl_endian.h curl_des.h \
|
||||
curl_printf.h system_win32.h rand.h mime.h curl_sha256.h setopt.h \
|
||||
curl_path.h curl_ctype.h curl_range.h psl.h doh.h urlapi-int.h \
|
||||
curl_get_line.h altsvc.h
|
||||
curl_get_line.h altsvc.h quic.h socketpair.h rename.h
|
||||
|
||||
LIB_RCFILES = libcurl.rc
|
||||
|
||||
CSOURCES = $(LIB_CFILES) $(LIB_VAUTH_CFILES) $(LIB_VTLS_CFILES)
|
||||
HHEADERS = $(LIB_HFILES) $(LIB_VAUTH_HFILES) $(LIB_VTLS_HFILES)
|
||||
CSOURCES = $(LIB_CFILES) $(LIB_VAUTH_CFILES) $(LIB_VTLS_CFILES) \
|
||||
$(LIB_VQUIC_CFILES) $(LIB_VSSH_CFILES)
|
||||
HHEADERS = $(LIB_HFILES) $(LIB_VAUTH_HFILES) $(LIB_VTLS_HFILES) \
|
||||
$(LIB_VQUIC_HFILES) $(LIB_VSSH_HFILES)
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 2019 - 2020, 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
|
||||
@ -34,6 +34,8 @@
|
||||
#include "parsedate.h"
|
||||
#include "sendf.h"
|
||||
#include "warnless.h"
|
||||
#include "rand.h"
|
||||
#include "rename.h"
|
||||
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
@ -48,15 +50,19 @@
|
||||
#define MAX_ALTSVC_ALPNLENSTR "10"
|
||||
#define MAX_ALTSVC_ALPNLEN 10
|
||||
|
||||
#if (defined(USE_QUICHE) || defined(USE_NGTCP2)) && !defined(UNITTESTS)
|
||||
#define H3VERSION "h3-27"
|
||||
#else
|
||||
#define H3VERSION "h3"
|
||||
#endif
|
||||
|
||||
static enum alpnid alpn2alpnid(char *name)
|
||||
{
|
||||
if(strcasecompare(name, "h1"))
|
||||
return ALPN_h1;
|
||||
if(strcasecompare(name, "h2"))
|
||||
return ALPN_h2;
|
||||
if(strcasecompare(name, "h2c"))
|
||||
return ALPN_h2c;
|
||||
if(strcasecompare(name, "h3"))
|
||||
if(strcasecompare(name, H3VERSION))
|
||||
return ALPN_h3;
|
||||
return ALPN_none; /* unknown, probably rubbish input */
|
||||
}
|
||||
@ -69,10 +75,8 @@ const char *Curl_alpnid2str(enum alpnid id)
|
||||
return "h1";
|
||||
case ALPN_h2:
|
||||
return "h2";
|
||||
case ALPN_h2c:
|
||||
return "h2c";
|
||||
case ALPN_h3:
|
||||
return "h3";
|
||||
return H3VERSION;
|
||||
default:
|
||||
return ""; /* bad */
|
||||
}
|
||||
@ -81,8 +85,8 @@ const char *Curl_alpnid2str(enum alpnid id)
|
||||
|
||||
static void altsvc_free(struct altsvc *as)
|
||||
{
|
||||
free(as->srchost);
|
||||
free(as->dsthost);
|
||||
free(as->src.host);
|
||||
free(as->dst.host);
|
||||
free(as);
|
||||
}
|
||||
|
||||
@ -97,17 +101,17 @@ static struct altsvc *altsvc_createid(const char *srchost,
|
||||
if(!as)
|
||||
return NULL;
|
||||
|
||||
as->srchost = strdup(srchost);
|
||||
if(!as->srchost)
|
||||
as->src.host = strdup(srchost);
|
||||
if(!as->src.host)
|
||||
goto error;
|
||||
as->dsthost = strdup(dsthost);
|
||||
if(!as->dsthost)
|
||||
as->dst.host = strdup(dsthost);
|
||||
if(!as->dst.host)
|
||||
goto error;
|
||||
|
||||
as->srcalpnid = srcalpnid;
|
||||
as->dstalpnid = dstalpnid;
|
||||
as->srcport = curlx_ultous(srcport);
|
||||
as->dstport = curlx_ultous(dstport);
|
||||
as->src.alpnid = srcalpnid;
|
||||
as->dst.alpnid = dstalpnid;
|
||||
as->src.port = curlx_ultous(srcport);
|
||||
as->dst.port = curlx_ultous(dstport);
|
||||
|
||||
return as;
|
||||
error:
|
||||
@ -156,7 +160,7 @@ static CURLcode altsvc_add(struct altsvcinfo *asi, char *line)
|
||||
date, &persist, &prio);
|
||||
if(9 == rc) {
|
||||
struct altsvc *as;
|
||||
time_t expires = curl_getdate(date, NULL);
|
||||
time_t expires = Curl_getdate_capped(date);
|
||||
as = altsvc_create(srchost, dsthost, srcalpn, dstalpn, srcport, dstport);
|
||||
if(as) {
|
||||
as->expires = expires;
|
||||
@ -183,7 +187,16 @@ static CURLcode altsvc_load(struct altsvcinfo *asi, const char *file)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
char *line = NULL;
|
||||
FILE *fp = fopen(file, FOPEN_READTEXT);
|
||||
FILE *fp;
|
||||
|
||||
/* we need a private copy of the file name so that the altsvc cache file
|
||||
name survives an easy handle reset */
|
||||
free(asi->filename);
|
||||
asi->filename = strdup(file);
|
||||
if(!asi->filename)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
fp = fopen(file, FOPEN_READTEXT);
|
||||
if(fp) {
|
||||
line = malloc(MAX_ALTSVC_LINE);
|
||||
if(!line)
|
||||
@ -204,6 +217,7 @@ static CURLcode altsvc_load(struct altsvcinfo *asi, const char *file)
|
||||
return result;
|
||||
|
||||
fail:
|
||||
Curl_safefree(asi->filename);
|
||||
free(line);
|
||||
fclose(fp);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
@ -226,8 +240,8 @@ static CURLcode altsvc_out(struct altsvc *as, FILE *fp)
|
||||
"\"%d%02d%02d "
|
||||
"%02d:%02d:%02d\" "
|
||||
"%u %d\n",
|
||||
Curl_alpnid2str(as->srcalpnid), as->srchost, as->srcport,
|
||||
Curl_alpnid2str(as->dstalpnid), as->dsthost, as->dstport,
|
||||
Curl_alpnid2str(as->src.alpnid), as->src.host, as->src.port,
|
||||
Curl_alpnid2str(as->dst.alpnid), as->dst.host, 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);
|
||||
@ -252,7 +266,7 @@ struct altsvcinfo *Curl_altsvc_init(void)
|
||||
#ifdef USE_NGHTTP2
|
||||
| CURLALTSVC_H2
|
||||
#endif
|
||||
#ifdef USE_HTTP3
|
||||
#ifdef ENABLE_QUIC
|
||||
| CURLALTSVC_H3
|
||||
#endif
|
||||
;
|
||||
@ -297,6 +311,7 @@ void Curl_altsvc_cleanup(struct altsvcinfo *altsvc)
|
||||
n = e->next;
|
||||
altsvc_free(as);
|
||||
}
|
||||
free(altsvc->filename);
|
||||
free(altsvc);
|
||||
}
|
||||
}
|
||||
@ -304,34 +319,57 @@ void Curl_altsvc_cleanup(struct altsvcinfo *altsvc)
|
||||
/*
|
||||
* Curl_altsvc_save() writes the altsvc cache to a file.
|
||||
*/
|
||||
CURLcode Curl_altsvc_save(struct altsvcinfo *altsvc, const char *file)
|
||||
CURLcode Curl_altsvc_save(struct Curl_easy *data,
|
||||
struct altsvcinfo *altsvc, const char *file)
|
||||
{
|
||||
struct curl_llist_element *e;
|
||||
struct curl_llist_element *n;
|
||||
CURLcode result = CURLE_OK;
|
||||
FILE *out;
|
||||
char *tempstore;
|
||||
unsigned char randsuffix[9];
|
||||
|
||||
if(!altsvc)
|
||||
/* no cache activated */
|
||||
return CURLE_OK;
|
||||
|
||||
if((altsvc->flags & CURLALTSVC_READONLYFILE) || !file[0])
|
||||
/* marked as read-only or zero length file name */
|
||||
/* if not new name is given, use the one we stored from the load */
|
||||
if(!file && altsvc->filename)
|
||||
file = altsvc->filename;
|
||||
|
||||
if((altsvc->flags & CURLALTSVC_READONLYFILE) || !file || !file[0])
|
||||
/* marked as read-only, no file or zero length file name */
|
||||
return CURLE_OK;
|
||||
out = fopen(file, FOPEN_WRITETEXT);
|
||||
|
||||
if(Curl_rand_hex(data, randsuffix, sizeof(randsuffix)))
|
||||
return CURLE_FAILED_INIT;
|
||||
|
||||
tempstore = aprintf("%s.%s.tmp", file, randsuffix);
|
||||
if(!tempstore)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
out = fopen(tempstore, FOPEN_WRITETEXT);
|
||||
if(!out)
|
||||
return CURLE_WRITE_ERROR;
|
||||
fputs("# Your alt-svc cache. https://curl.haxx.se/docs/alt-svc.html\n"
|
||||
"# This file was generated by libcurl! Edit at your own risk.\n",
|
||||
out);
|
||||
for(e = altsvc->list.head; e; e = n) {
|
||||
struct altsvc *as = e->ptr;
|
||||
n = e->next;
|
||||
result = altsvc_out(as, out);
|
||||
result = CURLE_WRITE_ERROR;
|
||||
else {
|
||||
fputs("# Your alt-svc cache. https://curl.haxx.se/docs/alt-svc.html\n"
|
||||
"# This file was generated by libcurl! Edit at your own risk.\n",
|
||||
out);
|
||||
for(e = altsvc->list.head; e; e = n) {
|
||||
struct altsvc *as = e->ptr;
|
||||
n = e->next;
|
||||
result = altsvc_out(as, out);
|
||||
if(result)
|
||||
break;
|
||||
}
|
||||
fclose(out);
|
||||
if(!result && Curl_rename(tempstore, file))
|
||||
result = CURLE_WRITE_ERROR;
|
||||
|
||||
if(result)
|
||||
break;
|
||||
unlink(tempstore);
|
||||
}
|
||||
fclose(out);
|
||||
free(tempstore);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -343,15 +381,15 @@ static CURLcode getalnum(const char **ptr, char *alpnbuf, size_t buflen)
|
||||
while(*p && ISBLANK(*p))
|
||||
p++;
|
||||
protop = p;
|
||||
while(*p && ISALNUM(*p))
|
||||
while(*p && !ISBLANK(*p) && (*p != ';') && (*p != '='))
|
||||
p++;
|
||||
len = p - protop;
|
||||
*ptr = p;
|
||||
|
||||
if(!len || (len >= buflen))
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
memcpy(alpnbuf, protop, len);
|
||||
alpnbuf[len] = 0;
|
||||
*ptr = p;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
@ -365,9 +403,9 @@ static void altsvc_flush(struct altsvcinfo *asi, enum alpnid srcalpnid,
|
||||
for(e = asi->list.head; e; e = n) {
|
||||
struct altsvc *as = e->ptr;
|
||||
n = e->next;
|
||||
if((srcalpnid == as->srcalpnid) &&
|
||||
(srcport == as->srcport) &&
|
||||
strcasecompare(srchost, as->srchost)) {
|
||||
if((srcalpnid == as->src.alpnid) &&
|
||||
(srcport == as->src.port) &&
|
||||
strcasecompare(srchost, as->src.host)) {
|
||||
Curl_llist_remove(&asi->list, e, NULL);
|
||||
altsvc_free(as);
|
||||
asi->num--;
|
||||
@ -397,6 +435,10 @@ static time_t debugtime(void *unused)
|
||||
*
|
||||
* 'value' points to the header *value*. That's contents to the right of the
|
||||
* header name.
|
||||
*
|
||||
* Currently this function rejects invalid data without returning an error.
|
||||
* Invalid host name, port number will result in the specific alternative
|
||||
* being rejected. Unknown protocols are skipped.
|
||||
*/
|
||||
CURLcode Curl_altsvc_parse(struct Curl_easy *data,
|
||||
struct altsvcinfo *asi, const char *value,
|
||||
@ -410,12 +452,11 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
|
||||
char alpnbuf[MAX_ALTSVC_ALPNLEN] = "";
|
||||
struct altsvc *as;
|
||||
unsigned short dstport = srcport; /* the same by default */
|
||||
const char *semip;
|
||||
time_t maxage = 24 * 3600; /* default is 24 hours */
|
||||
bool persist = FALSE;
|
||||
CURLcode result = getalnum(&p, alpnbuf, sizeof(alpnbuf));
|
||||
if(result)
|
||||
return result;
|
||||
if(result) {
|
||||
infof(data, "Excessive alt-svc header, ignoring...\n");
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
DEBUGASSERT(asi);
|
||||
|
||||
@ -427,47 +468,20 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/* The 'ma' and 'persist' flags are annoyingly meant for all alternatives
|
||||
but are set after the list on the line. Scan for the semicolons and get
|
||||
those fields first! */
|
||||
semip = p;
|
||||
do {
|
||||
semip = strchr(semip, ';');
|
||||
if(semip) {
|
||||
char option[32];
|
||||
unsigned long num;
|
||||
char *end_ptr;
|
||||
semip++; /* pass the semicolon */
|
||||
result = getalnum(&semip, option, sizeof(option));
|
||||
if(result)
|
||||
break;
|
||||
while(*semip && ISBLANK(*semip))
|
||||
semip++;
|
||||
if(*semip != '=')
|
||||
continue;
|
||||
semip++;
|
||||
num = strtoul(semip, &end_ptr, 10);
|
||||
if(num < ULONG_MAX) {
|
||||
if(strcasecompare("ma", option))
|
||||
maxage = num;
|
||||
else if(strcasecompare("persist", option) && (num == 1))
|
||||
persist = TRUE;
|
||||
}
|
||||
semip = end_ptr;
|
||||
}
|
||||
} while(semip);
|
||||
|
||||
do {
|
||||
if(*p == '=') {
|
||||
/* [protocol]="[host][:port]" */
|
||||
dstalpnid = alpn2alpnid(alpnbuf);
|
||||
if(!dstalpnid) {
|
||||
infof(data, "Unknown alt-svc protocol \"%s\", ignoring...\n", alpnbuf);
|
||||
return CURLE_OK;
|
||||
}
|
||||
p++;
|
||||
if(*p == '\"') {
|
||||
const char *dsthost;
|
||||
const char *value_ptr;
|
||||
char option[32];
|
||||
unsigned long num;
|
||||
char *end_ptr;
|
||||
bool quoted = FALSE;
|
||||
time_t maxage = 24 * 3600; /* default is 24 hours */
|
||||
bool persist = FALSE;
|
||||
p++;
|
||||
if(*p != ':') {
|
||||
/* host name starts here */
|
||||
@ -475,11 +489,15 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
|
||||
while(*p && (ISALNUM(*p) || (*p == '.') || (*p == '-')))
|
||||
p++;
|
||||
len = p - hostp;
|
||||
if(!len || (len >= MAX_ALTSVC_HOSTLEN))
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
memcpy(namebuf, hostp, len);
|
||||
namebuf[len] = 0;
|
||||
dsthost = namebuf;
|
||||
if(!len || (len >= MAX_ALTSVC_HOSTLEN)) {
|
||||
infof(data, "Excessive alt-svc host name, ignoring...\n");
|
||||
dstalpnid = ALPN_none;
|
||||
}
|
||||
else {
|
||||
memcpy(namebuf, hostp, len);
|
||||
namebuf[len] = 0;
|
||||
dsthost = namebuf;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* no destination name, use source host */
|
||||
@ -487,31 +505,86 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
|
||||
}
|
||||
if(*p == ':') {
|
||||
/* a port number */
|
||||
char *end_ptr;
|
||||
unsigned long port = strtoul(++p, &end_ptr, 10);
|
||||
if(port > USHRT_MAX || end_ptr == p || *end_ptr != '\"') {
|
||||
infof(data, "Unknown alt-svc port number, ignoring...\n");
|
||||
return CURLE_OK;
|
||||
dstalpnid = ALPN_none;
|
||||
}
|
||||
p = end_ptr;
|
||||
dstport = curlx_ultous(port);
|
||||
}
|
||||
if(*p++ != '\"')
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
as = altsvc_createid(srchost, dsthost,
|
||||
srcalpnid, dstalpnid,
|
||||
srcport, dstport);
|
||||
if(as) {
|
||||
/* The expires time also needs to take the Age: value (if any) into
|
||||
account. [See RFC 7838 section 3.1] */
|
||||
as->expires = maxage + time(NULL);
|
||||
as->persist = persist;
|
||||
Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node);
|
||||
asi->num++; /* one more entry */
|
||||
infof(data, "Added alt-svc: %s:%d over %s\n", dsthost, dstport,
|
||||
Curl_alpnid2str(dstalpnid));
|
||||
break;
|
||||
/* Handle the optional 'ma' and 'persist' flags. Unknown flags
|
||||
are skipped. */
|
||||
for(;;) {
|
||||
while(*p && ISBLANK(*p) && *p != ';' && *p != ',')
|
||||
p++;
|
||||
if(!*p || *p == ',')
|
||||
break;
|
||||
p++; /* pass the semicolon */
|
||||
if(!*p)
|
||||
break;
|
||||
result = getalnum(&p, option, sizeof(option));
|
||||
if(result) {
|
||||
/* skip option if name is too long */
|
||||
option[0] = '\0';
|
||||
}
|
||||
while(*p && ISBLANK(*p))
|
||||
p++;
|
||||
if(*p != '=')
|
||||
return CURLE_OK;
|
||||
p++;
|
||||
while(*p && ISBLANK(*p))
|
||||
p++;
|
||||
if(!*p)
|
||||
return CURLE_OK;
|
||||
if(*p == '\"') {
|
||||
/* quoted value */
|
||||
p++;
|
||||
quoted = TRUE;
|
||||
}
|
||||
value_ptr = p;
|
||||
if(quoted) {
|
||||
while(*p && *p != '\"')
|
||||
p++;
|
||||
if(!*p++)
|
||||
return CURLE_OK;
|
||||
}
|
||||
else {
|
||||
while(*p && !ISBLANK(*p) && *p!= ';' && *p != ',')
|
||||
p++;
|
||||
}
|
||||
num = strtoul(value_ptr, &end_ptr, 10);
|
||||
if((end_ptr != value_ptr) && (num < ULONG_MAX)) {
|
||||
if(strcasecompare("ma", option))
|
||||
maxage = num;
|
||||
else if(strcasecompare("persist", option) && (num == 1))
|
||||
persist = TRUE;
|
||||
}
|
||||
}
|
||||
if(dstalpnid) {
|
||||
as = altsvc_createid(srchost, dsthost,
|
||||
srcalpnid, dstalpnid,
|
||||
srcport, dstport);
|
||||
if(as) {
|
||||
/* The expires time also needs to take the Age: value (if any) into
|
||||
account. [See RFC 7838 section 3.1] */
|
||||
as->expires = maxage + time(NULL);
|
||||
as->persist = persist;
|
||||
Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node);
|
||||
asi->num++; /* one more entry */
|
||||
infof(data, "Added alt-svc: %s:%d over %s\n", dsthost, dstport,
|
||||
Curl_alpnid2str(dstalpnid));
|
||||
}
|
||||
}
|
||||
else {
|
||||
infof(data, "Unknown alt-svc protocol \"%s\", skipping...\n",
|
||||
alpnbuf);
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
/* after the double quote there can be a comma if there's another
|
||||
string or a semicolon if no more */
|
||||
if(*p == ',') {
|
||||
@ -519,11 +592,11 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
|
||||
p++;
|
||||
result = getalnum(&p, alpnbuf, sizeof(alpnbuf));
|
||||
if(result)
|
||||
/* failed to parse, but since we already did at least one host we
|
||||
return OK */
|
||||
return CURLE_OK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
} while(*p && (*p != ';') && (*p != '\n') && (*p != '\r'));
|
||||
|
||||
return CURLE_OK;
|
||||
@ -535,31 +608,31 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
|
||||
bool Curl_altsvc_lookup(struct altsvcinfo *asi,
|
||||
enum alpnid srcalpnid, const char *srchost,
|
||||
int srcport,
|
||||
enum alpnid *dstalpnid, const char **dsthost,
|
||||
int *dstport)
|
||||
struct altsvc **dstentry,
|
||||
const int versions) /* one or more bits */
|
||||
{
|
||||
struct curl_llist_element *e;
|
||||
struct curl_llist_element *n;
|
||||
time_t now = time(NULL);
|
||||
DEBUGASSERT(asi);
|
||||
DEBUGASSERT(srchost);
|
||||
DEBUGASSERT(dsthost);
|
||||
DEBUGASSERT(dstentry);
|
||||
|
||||
for(e = asi->list.head; e; e = n) {
|
||||
struct altsvc *as = e->ptr;
|
||||
n = e->next;
|
||||
if(as->expires < now) {
|
||||
/* an expired entry, remove */
|
||||
Curl_llist_remove(&asi->list, e, NULL);
|
||||
altsvc_free(as);
|
||||
continue;
|
||||
}
|
||||
if((as->srcalpnid == srcalpnid) &&
|
||||
strcasecompare(as->srchost, srchost) &&
|
||||
as->srcport == srcport) {
|
||||
if((as->src.alpnid == srcalpnid) &&
|
||||
strcasecompare(as->src.host, srchost) &&
|
||||
(as->src.port == srcport) &&
|
||||
(versions & as->dst.alpnid)) {
|
||||
/* match */
|
||||
*dstalpnid = as->dstalpnid;
|
||||
*dsthost = as->dsthost;
|
||||
*dstport = as->dstport;
|
||||
*dstentry = as;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 2019 - 2020, 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
|
||||
@ -28,20 +28,21 @@
|
||||
#include "llist.h"
|
||||
|
||||
enum alpnid {
|
||||
ALPN_none,
|
||||
ALPN_h1,
|
||||
ALPN_h2,
|
||||
ALPN_h2c,
|
||||
ALPN_h3
|
||||
ALPN_none = 0,
|
||||
ALPN_h1 = CURLALTSVC_H1,
|
||||
ALPN_h2 = CURLALTSVC_H2,
|
||||
ALPN_h3 = CURLALTSVC_H3
|
||||
};
|
||||
|
||||
struct althost {
|
||||
char *host;
|
||||
unsigned short port;
|
||||
enum alpnid alpnid;
|
||||
};
|
||||
|
||||
struct altsvc {
|
||||
char *srchost;
|
||||
char *dsthost;
|
||||
unsigned short srcport;
|
||||
unsigned short dstport;
|
||||
enum alpnid srcalpnid;
|
||||
enum alpnid dstalpnid;
|
||||
struct althost src;
|
||||
struct althost dst;
|
||||
time_t expires;
|
||||
bool persist;
|
||||
int prio;
|
||||
@ -58,7 +59,8 @@ struct altsvcinfo {
|
||||
const char *Curl_alpnid2str(enum alpnid id);
|
||||
struct altsvcinfo *Curl_altsvc_init(void);
|
||||
CURLcode Curl_altsvc_load(struct altsvcinfo *asi, const char *file);
|
||||
CURLcode Curl_altsvc_save(struct altsvcinfo *asi, const char *file);
|
||||
CURLcode Curl_altsvc_save(struct Curl_easy *data,
|
||||
struct altsvcinfo *asi, const char *file);
|
||||
CURLcode Curl_altsvc_ctrl(struct altsvcinfo *asi, const long ctrl);
|
||||
void Curl_altsvc_cleanup(struct altsvcinfo *altsvc);
|
||||
CURLcode Curl_altsvc_parse(struct Curl_easy *data,
|
||||
@ -68,10 +70,10 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
|
||||
bool Curl_altsvc_lookup(struct altsvcinfo *asi,
|
||||
enum alpnid srcalpnid, const char *srchost,
|
||||
int srcport,
|
||||
enum alpnid *dstalpnid, const char **dsthost,
|
||||
int *dstport);
|
||||
struct altsvc **dstentry,
|
||||
const int versions); /* CURLALTSVC_H* bits */
|
||||
#else
|
||||
/* disabled */
|
||||
#define Curl_altsvc_save(a,b)
|
||||
#define Curl_altsvc_save(a,b,c)
|
||||
#endif /* CURL_DISABLE_HTTP || USE_ALTSVC */
|
||||
#endif /* HEADER_CURL_ALTSVC_H */
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2020, 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
|
||||
@ -253,16 +253,14 @@ static void destroy_async_data(struct Curl_async *async)
|
||||
*/
|
||||
|
||||
int Curl_resolver_getsock(struct connectdata *conn,
|
||||
curl_socket_t *socks,
|
||||
int numsocks)
|
||||
|
||||
curl_socket_t *socks)
|
||||
{
|
||||
struct timeval maxtime;
|
||||
struct timeval timebuf;
|
||||
struct timeval *timeout;
|
||||
long milli;
|
||||
int max = ares_getsock((ares_channel)conn->data->state.resolver,
|
||||
(ares_socket_t *)socks, numsocks);
|
||||
(ares_socket_t *)socks, MAX_SOCKSPEREASYHANDLE);
|
||||
|
||||
maxtime.tv_sec = CURL_TIMEOUT_RESOLVE;
|
||||
maxtime.tv_usec = 0;
|
||||
@ -628,26 +626,11 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
|
||||
{
|
||||
char *bufp;
|
||||
struct Curl_easy *data = conn->data;
|
||||
struct in_addr in;
|
||||
int family = PF_INET;
|
||||
#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */
|
||||
struct in6_addr in6;
|
||||
#endif /* CURLRES_IPV6 */
|
||||
|
||||
*waitp = 0; /* default to synchronous response */
|
||||
|
||||
/* First check if this is an IPv4 address string */
|
||||
if(Curl_inet_pton(AF_INET, hostname, &in) > 0) {
|
||||
/* This is a dotted IP address 123.123.123.123-style */
|
||||
return Curl_ip2addr(AF_INET, &in, hostname, port);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */
|
||||
/* Otherwise, check if this is an IPv6 address string */
|
||||
if(Curl_inet_pton (AF_INET6, hostname, &in6) > 0)
|
||||
/* This must be an IPv6 address literal. */
|
||||
return Curl_ip2addr(AF_INET6, &in6, hostname, port);
|
||||
|
||||
switch(conn->ip_version) {
|
||||
default:
|
||||
#if ARES_VERSION >= 0x010601
|
||||
@ -686,7 +669,7 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
|
||||
res->last_status = ARES_ENOTFOUND;
|
||||
#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */
|
||||
if(family == PF_UNSPEC) {
|
||||
if(Curl_ipv6works()) {
|
||||
if(Curl_ipv6works(conn)) {
|
||||
res->num_pending = 2;
|
||||
|
||||
/* areschannel is already setup in the Curl_open() function */
|
||||
@ -734,7 +717,11 @@ CURLcode Curl_set_dns_servers(struct Curl_easy *data,
|
||||
return CURLE_OK;
|
||||
|
||||
#if (ARES_VERSION >= 0x010704)
|
||||
#if (ARES_VERSION >= 0x010b00)
|
||||
ares_result = ares_set_servers_ports_csv(data->state.resolver, servers);
|
||||
#else
|
||||
ares_result = ares_set_servers_csv(data->state.resolver, servers);
|
||||
#endif
|
||||
switch(ares_result) {
|
||||
case ARES_SUCCESS:
|
||||
result = CURLE_OK;
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2020, 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
|
||||
@ -21,6 +21,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include "curl_setup.h"
|
||||
#include "socketpair.h"
|
||||
|
||||
/***********************************************************************
|
||||
* Only for threaded name resolves builds
|
||||
@ -70,10 +71,10 @@
|
||||
#include "strerror.h"
|
||||
#include "url.h"
|
||||
#include "multiif.h"
|
||||
#include "inet_pton.h"
|
||||
#include "inet_ntop.h"
|
||||
#include "curl_threads.h"
|
||||
#include "connect.h"
|
||||
#include "socketpair.h"
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
@ -163,6 +164,10 @@ struct thread_sync_data {
|
||||
char *hostname; /* hostname to resolve, Curl_async.hostname
|
||||
duplicate */
|
||||
int port;
|
||||
#ifdef USE_SOCKETPAIR
|
||||
struct connectdata *conn;
|
||||
curl_socket_t sock_pair[2]; /* socket pair */
|
||||
#endif
|
||||
int sock_error;
|
||||
Curl_addrinfo *res;
|
||||
#ifdef HAVE_GETADDRINFO
|
||||
@ -197,6 +202,15 @@ void destroy_thread_sync_data(struct thread_sync_data * tsd)
|
||||
if(tsd->res)
|
||||
Curl_freeaddrinfo(tsd->res);
|
||||
|
||||
#ifdef USE_SOCKETPAIR
|
||||
/*
|
||||
* close one end of the socket pair (may be done in resolver thread);
|
||||
* the other end (for reading) is always closed in the parent thread.
|
||||
*/
|
||||
if(tsd->sock_pair[1] != CURL_SOCKET_BAD) {
|
||||
sclose(tsd->sock_pair[1]);
|
||||
}
|
||||
#endif
|
||||
memset(tsd, 0, sizeof(*tsd));
|
||||
}
|
||||
|
||||
@ -230,6 +244,14 @@ int init_thread_sync_data(struct thread_data * td,
|
||||
|
||||
Curl_mutex_init(tsd->mtx);
|
||||
|
||||
#ifdef USE_SOCKETPAIR
|
||||
/* create socket pair, avoid AF_LOCAL since it doesn't build on Solaris */
|
||||
if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, &tsd->sock_pair[0]) < 0) {
|
||||
tsd->sock_pair[0] = CURL_SOCKET_BAD;
|
||||
tsd->sock_pair[1] = CURL_SOCKET_BAD;
|
||||
goto err_exit;
|
||||
}
|
||||
#endif
|
||||
tsd->sock_error = CURL_ASYNC_SUCCESS;
|
||||
|
||||
/* Copying hostname string because original can be destroyed by parent
|
||||
@ -276,6 +298,9 @@ static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg)
|
||||
struct thread_data *td = tsd->td;
|
||||
char service[12];
|
||||
int rc;
|
||||
#ifdef USE_SOCKETPAIR
|
||||
char buf[1];
|
||||
#endif
|
||||
|
||||
msnprintf(service, sizeof(service), "%d", tsd->port);
|
||||
|
||||
@ -298,6 +323,16 @@ static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg)
|
||||
free(td);
|
||||
}
|
||||
else {
|
||||
#ifdef USE_SOCKETPAIR
|
||||
if(tsd->sock_pair[1] != CURL_SOCKET_BAD) {
|
||||
/* DNS has been resolved, signal client task */
|
||||
buf[0] = 1;
|
||||
if(swrite(tsd->sock_pair[1], buf, sizeof(buf)) < 0) {
|
||||
/* update sock_erro to errno */
|
||||
tsd->sock_error = SOCKERRNO;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
tsd->done = 1;
|
||||
Curl_mutex_release(tsd->mtx);
|
||||
}
|
||||
@ -348,6 +383,10 @@ static void destroy_async_data(struct Curl_async *async)
|
||||
if(async->os_specific) {
|
||||
struct thread_data *td = (struct thread_data*) async->os_specific;
|
||||
int done;
|
||||
#ifdef USE_SOCKETPAIR
|
||||
curl_socket_t sock_rd = td->tsd.sock_pair[0];
|
||||
struct connectdata *conn = td->tsd.conn;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* if the thread is still blocking in the resolve syscall, detach it and
|
||||
@ -369,6 +408,15 @@ static void destroy_async_data(struct Curl_async *async)
|
||||
|
||||
free(async->os_specific);
|
||||
}
|
||||
#ifdef USE_SOCKETPAIR
|
||||
/*
|
||||
* ensure CURLMOPT_SOCKETFUNCTION fires CURL_POLL_REMOVE
|
||||
* before the FD is invalidated to avoid EBADF on EPOLL_CTL_DEL
|
||||
*/
|
||||
if(conn)
|
||||
Curl_multi_closed(conn->data, sock_rd);
|
||||
sclose(sock_rd);
|
||||
#endif
|
||||
}
|
||||
async->os_specific = NULL;
|
||||
|
||||
@ -569,8 +617,9 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
|
||||
}
|
||||
else {
|
||||
/* poll for name lookup done with exponential backoff up to 250ms */
|
||||
timediff_t elapsed = Curl_timediff(Curl_now(),
|
||||
data->progress.t_startsingle);
|
||||
/* should be fine even if this converts to 32 bit */
|
||||
time_t elapsed = (time_t)Curl_timediff(Curl_now(),
|
||||
data->progress.t_startsingle);
|
||||
if(elapsed < 0)
|
||||
elapsed = 0;
|
||||
|
||||
@ -592,26 +641,45 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
|
||||
}
|
||||
|
||||
int Curl_resolver_getsock(struct connectdata *conn,
|
||||
curl_socket_t *socks,
|
||||
int numsocks)
|
||||
curl_socket_t *socks)
|
||||
{
|
||||
int ret_val = 0;
|
||||
time_t milli;
|
||||
timediff_t ms;
|
||||
struct Curl_easy *data = conn->data;
|
||||
struct resdata *reslv = (struct resdata *)data->state.resolver;
|
||||
#ifdef USE_SOCKETPAIR
|
||||
struct thread_data *td = (struct thread_data*)conn->async.os_specific;
|
||||
#else
|
||||
(void)socks;
|
||||
(void)numsocks;
|
||||
ms = Curl_timediff(Curl_now(), reslv->start);
|
||||
if(ms < 3)
|
||||
milli = 0;
|
||||
else if(ms <= 50)
|
||||
milli = ms/3;
|
||||
else if(ms <= 250)
|
||||
milli = 50;
|
||||
else
|
||||
milli = 200;
|
||||
Curl_expire(data, milli, EXPIRE_ASYNC_NAME);
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
#ifdef USE_SOCKETPAIR
|
||||
if(td) {
|
||||
/* return read fd to client for polling the DNS resolution status */
|
||||
socks[0] = td->tsd.sock_pair[0];
|
||||
DEBUGASSERT(td->tsd.conn == conn || !td->tsd.conn);
|
||||
td->tsd.conn = conn;
|
||||
ret_val = GETSOCK_READSOCK(0);
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
ms = Curl_timediff(Curl_now(), reslv->start);
|
||||
if(ms < 3)
|
||||
milli = 0;
|
||||
else if(ms <= 50)
|
||||
milli = (time_t)ms/3;
|
||||
else if(ms <= 250)
|
||||
milli = 50;
|
||||
else
|
||||
milli = 200;
|
||||
Curl_expire(data, milli, EXPIRE_ASYNC_NAME);
|
||||
#ifdef USE_SOCKETPAIR
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
#ifndef HAVE_GETADDRINFO
|
||||
@ -623,16 +691,11 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
|
||||
int port,
|
||||
int *waitp)
|
||||
{
|
||||
struct in_addr in;
|
||||
struct Curl_easy *data = conn->data;
|
||||
struct resdata *reslv = (struct resdata *)data->state.resolver;
|
||||
|
||||
*waitp = 0; /* default to synchronous response */
|
||||
|
||||
if(Curl_inet_pton(AF_INET, hostname, &in) > 0)
|
||||
/* This is a dotted IP address 123.123.123.123-style */
|
||||
return Curl_ip2addr(AF_INET, &in, hostname, port);
|
||||
|
||||
reslv->start = Curl_now();
|
||||
|
||||
/* fire up a new resolver thread! */
|
||||
@ -657,32 +720,12 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
|
||||
int *waitp)
|
||||
{
|
||||
struct addrinfo hints;
|
||||
char sbuf[12];
|
||||
int pf = PF_INET;
|
||||
struct Curl_easy *data = conn->data;
|
||||
struct resdata *reslv = (struct resdata *)data->state.resolver;
|
||||
|
||||
*waitp = 0; /* default to synchronous response */
|
||||
|
||||
#ifndef USE_RESOLVE_ON_IPS
|
||||
{
|
||||
struct in_addr in;
|
||||
/* First check if this is an IPv4 address string */
|
||||
if(Curl_inet_pton(AF_INET, hostname, &in) > 0)
|
||||
/* This is a dotted IP address 123.123.123.123-style */
|
||||
return Curl_ip2addr(AF_INET, &in, hostname, port);
|
||||
}
|
||||
#ifdef CURLRES_IPV6
|
||||
{
|
||||
struct in6_addr in6;
|
||||
/* check if this is an IPv6 address string */
|
||||
if(Curl_inet_pton(AF_INET6, hostname, &in6) > 0)
|
||||
/* This is an IPv6 address literal */
|
||||
return Curl_ip2addr(AF_INET6, &in6, hostname, port);
|
||||
}
|
||||
#endif /* CURLRES_IPV6 */
|
||||
#endif /* !USE_RESOLVE_ON_IPS */
|
||||
|
||||
#ifdef CURLRES_IPV6
|
||||
/*
|
||||
* Check if a limited name resolve has been requested.
|
||||
@ -699,16 +742,15 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
|
||||
break;
|
||||
}
|
||||
|
||||
if((pf != PF_INET) && !Curl_ipv6works())
|
||||
if((pf != PF_INET) && !Curl_ipv6works(conn))
|
||||
/* The stack seems to be a non-IPv6 one */
|
||||
pf = PF_INET;
|
||||
#endif /* CURLRES_IPV6 */
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = pf;
|
||||
hints.ai_socktype = conn->socktype;
|
||||
|
||||
msnprintf(sbuf, sizeof(sbuf), "%d", port);
|
||||
hints.ai_socktype = (conn->transport == TRNSPRT_TCP)?
|
||||
SOCK_STREAM : SOCK_DGRAM;
|
||||
|
||||
reslv->start = Curl_now();
|
||||
/* fire up a new resolver thread! */
|
||||
|
@ -114,8 +114,7 @@ void Curl_resolver_kill(struct connectdata *conn);
|
||||
* return bitmask indicating what file descriptors (referring to array indexes
|
||||
* in the 'sock' array) to wait for, read/write.
|
||||
*/
|
||||
int Curl_resolver_getsock(struct connectdata *conn, curl_socket_t *sock,
|
||||
int numsocks);
|
||||
int Curl_resolver_getsock(struct connectdata *conn, curl_socket_t *sock);
|
||||
|
||||
/*
|
||||
* Curl_resolver_is_resolved()
|
||||
|
@ -24,8 +24,8 @@
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#if !defined(CURL_DISABLE_HTTP_AUTH) || defined(USE_LIBSSH2) || \
|
||||
defined(USE_LIBSSH) || !defined(CURL_DISABLE_LDAP) || \
|
||||
#if !defined(CURL_DISABLE_HTTP_AUTH) || defined(USE_SSH) || \
|
||||
!defined(CURL_DISABLE_LDAP) || \
|
||||
!defined(CURL_DISABLE_DOH) || defined(USE_SSL)
|
||||
|
||||
#include "urldata.h" /* for the Curl_easy definition */
|
||||
|
@ -6,7 +6,7 @@
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2012 - 2016, Linus Nielsen Feltzing, <linus@haxx.se>
|
||||
* Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 2012 - 2020, 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
|
||||
@ -40,26 +40,7 @@
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
#ifdef CURLDEBUG
|
||||
/* the debug versions of these macros make extra certain that the lock is
|
||||
never doubly locked or unlocked */
|
||||
#define CONN_LOCK(x) if((x)->share) { \
|
||||
Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE); \
|
||||
DEBUGASSERT(!(x)->state.conncache_lock); \
|
||||
(x)->state.conncache_lock = TRUE; \
|
||||
}
|
||||
|
||||
#define CONN_UNLOCK(x) if((x)->share) { \
|
||||
DEBUGASSERT((x)->state.conncache_lock); \
|
||||
(x)->state.conncache_lock = FALSE; \
|
||||
Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT); \
|
||||
}
|
||||
#else
|
||||
#define CONN_LOCK(x) if((x)->share) \
|
||||
Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE)
|
||||
#define CONN_UNLOCK(x) if((x)->share) \
|
||||
Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT)
|
||||
#endif
|
||||
#define HASHKEY_SIZE 128
|
||||
|
||||
static void conn_llist_dtor(void *user, void *element)
|
||||
{
|
||||
@ -120,6 +101,7 @@ static int bundle_remove_conn(struct connectbundle *cb_ptr,
|
||||
}
|
||||
curr = curr->next;
|
||||
}
|
||||
DEBUGASSERT(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -141,10 +123,8 @@ int Curl_conncache_init(struct conncache *connc, int size)
|
||||
|
||||
rc = Curl_hash_init(&connc->hash, size, Curl_hash_str,
|
||||
Curl_str_key_compare, free_bundle_hash_entry);
|
||||
if(rc) {
|
||||
Curl_close(connc->closure_handle);
|
||||
connc->closure_handle = NULL;
|
||||
}
|
||||
if(rc)
|
||||
Curl_close(&connc->closure_handle);
|
||||
else
|
||||
connc->closure_handle->state.conn_cache = connc;
|
||||
|
||||
@ -159,23 +139,27 @@ void Curl_conncache_destroy(struct conncache *connc)
|
||||
|
||||
/* creates a key to find a bundle for this connection */
|
||||
static void hashkey(struct connectdata *conn, char *buf,
|
||||
size_t len) /* something like 128 is fine */
|
||||
size_t len, /* something like 128 is fine */
|
||||
const char **hostp)
|
||||
{
|
||||
const char *hostname;
|
||||
long port = conn->remote_port;
|
||||
|
||||
if(conn->bits.socksproxy)
|
||||
hostname = conn->socks_proxy.host.name;
|
||||
else if(conn->bits.httpproxy)
|
||||
if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
|
||||
hostname = conn->http_proxy.host.name;
|
||||
port = conn->port;
|
||||
}
|
||||
else if(conn->bits.conn_to_host)
|
||||
hostname = conn->conn_to_host.name;
|
||||
else
|
||||
hostname = conn->host.name;
|
||||
|
||||
DEBUGASSERT(len > 32);
|
||||
if(hostp)
|
||||
/* report back which name we used */
|
||||
*hostp = hostname;
|
||||
|
||||
/* put the number first so that the hostname gets cut off if too long */
|
||||
msnprintf(buf, len, "%ld%s", conn->port, hostname);
|
||||
msnprintf(buf, len, "%ld%s", port, hostname);
|
||||
}
|
||||
|
||||
void Curl_conncache_unlock(struct Curl_easy *data)
|
||||
@ -195,30 +179,19 @@ size_t Curl_conncache_size(struct Curl_easy *data)
|
||||
return num;
|
||||
}
|
||||
|
||||
/* Returns number of connections currently held in the connections's bundle
|
||||
Locks/unlocks the cache itself!
|
||||
*/
|
||||
size_t Curl_conncache_bundle_size(struct connectdata *conn)
|
||||
{
|
||||
size_t num;
|
||||
CONN_LOCK(conn->data);
|
||||
num = conn->bundle->num_connections;
|
||||
CONN_UNLOCK(conn->data);
|
||||
return num;
|
||||
}
|
||||
|
||||
/* Look up the bundle with all the connections to the same host this
|
||||
connectdata struct is setup to use.
|
||||
|
||||
**NOTE**: When it returns, it holds the connection cache lock! */
|
||||
struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn,
|
||||
struct conncache *connc)
|
||||
struct conncache *connc,
|
||||
const char **hostp)
|
||||
{
|
||||
struct connectbundle *bundle = NULL;
|
||||
CONN_LOCK(conn->data);
|
||||
if(connc) {
|
||||
char key[128];
|
||||
hashkey(conn, key, sizeof(key));
|
||||
char key[HASHKEY_SIZE];
|
||||
hashkey(conn, key, sizeof(key), hostp);
|
||||
bundle = Curl_hash_pick(&connc->hash, key, strlen(key));
|
||||
}
|
||||
|
||||
@ -267,17 +240,17 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc,
|
||||
struct Curl_easy *data = conn->data;
|
||||
|
||||
/* *find_bundle() locks the connection cache */
|
||||
bundle = Curl_conncache_find_bundle(conn, data->state.conn_cache);
|
||||
bundle = Curl_conncache_find_bundle(conn, data->state.conn_cache, NULL);
|
||||
if(!bundle) {
|
||||
int rc;
|
||||
char key[128];
|
||||
char key[HASHKEY_SIZE];
|
||||
|
||||
result = bundle_create(data, &new_bundle);
|
||||
if(result) {
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
hashkey(conn, key, sizeof(key));
|
||||
hashkey(conn, key, sizeof(key), NULL);
|
||||
rc = conncache_add_bundle(data->state.conn_cache, key, new_bundle);
|
||||
|
||||
if(!rc) {
|
||||
@ -423,17 +396,15 @@ conncache_find_first_connection(struct conncache *connc)
|
||||
*
|
||||
* Return TRUE if stored, FALSE if closed.
|
||||
*/
|
||||
bool Curl_conncache_return_conn(struct connectdata *conn)
|
||||
bool Curl_conncache_return_conn(struct Curl_easy *data,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
struct Curl_easy *data = conn->data;
|
||||
|
||||
/* data->multi->maxconnects can be negative, deal with it. */
|
||||
size_t maxconnects =
|
||||
(data->multi->maxconnects < 0) ? data->multi->num_easy * 4:
|
||||
data->multi->maxconnects;
|
||||
struct connectdata *conn_candidate = NULL;
|
||||
|
||||
conn->data = NULL; /* no owner anymore */
|
||||
conn->lastused = Curl_now(); /* it was used up until now */
|
||||
if(maxconnects > 0 &&
|
||||
Curl_conncache_size(data) > maxconnects) {
|
||||
@ -536,7 +507,8 @@ Curl_conncache_extract_oldest(struct Curl_easy *data)
|
||||
while(curr) {
|
||||
conn = curr->ptr;
|
||||
|
||||
if(!CONN_INUSE(conn) && !conn->data) {
|
||||
if(!CONN_INUSE(conn) && !conn->data && !conn->bits.close &&
|
||||
!conn->bits.connect_only) {
|
||||
/* Set higher score for the age passed since the connection was used */
|
||||
score = Curl_timediff(now, conn->lastused);
|
||||
|
||||
@ -588,7 +560,7 @@ void Curl_conncache_close_all_connections(struct conncache *connc)
|
||||
|
||||
Curl_hostcache_clean(connc->closure_handle,
|
||||
connc->closure_handle->dns.hostcache);
|
||||
Curl_close(connc->closure_handle);
|
||||
Curl_close(&connc->closure_handle);
|
||||
sigpipe_restore(&pipe_st);
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2015 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 2015 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 2012 - 2014, Linus Nielsen Feltzing, <linus@haxx.se>
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
@ -42,6 +42,27 @@ struct conncache {
|
||||
#define BUNDLE_UNKNOWN 0 /* initial value */
|
||||
#define BUNDLE_MULTIPLEX 2
|
||||
|
||||
#ifdef CURLDEBUG
|
||||
/* the debug versions of these macros make extra certain that the lock is
|
||||
never doubly locked or unlocked */
|
||||
#define CONN_LOCK(x) if((x)->share) { \
|
||||
Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE); \
|
||||
DEBUGASSERT(!(x)->state.conncache_lock); \
|
||||
(x)->state.conncache_lock = TRUE; \
|
||||
}
|
||||
|
||||
#define CONN_UNLOCK(x) if((x)->share) { \
|
||||
DEBUGASSERT((x)->state.conncache_lock); \
|
||||
(x)->state.conncache_lock = FALSE; \
|
||||
Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT); \
|
||||
}
|
||||
#else
|
||||
#define CONN_LOCK(x) if((x)->share) \
|
||||
Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE)
|
||||
#define CONN_UNLOCK(x) if((x)->share) \
|
||||
Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT)
|
||||
#endif
|
||||
|
||||
struct connectbundle {
|
||||
int multiuse; /* supports multi-use */
|
||||
size_t num_connections; /* Number of connections in the bundle */
|
||||
@ -54,13 +75,14 @@ void Curl_conncache_destroy(struct conncache *connc);
|
||||
|
||||
/* return the correct bundle, to a host or a proxy */
|
||||
struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn,
|
||||
struct conncache *connc);
|
||||
struct conncache *connc,
|
||||
const char **hostp);
|
||||
void Curl_conncache_unlock(struct Curl_easy *data);
|
||||
/* returns number of connections currently held in the connection cache */
|
||||
size_t Curl_conncache_size(struct Curl_easy *data);
|
||||
size_t Curl_conncache_bundle_size(struct connectdata *conn);
|
||||
|
||||
bool Curl_conncache_return_conn(struct connectdata *conn);
|
||||
bool Curl_conncache_return_conn(struct Curl_easy *data,
|
||||
struct connectdata *conn);
|
||||
CURLcode Curl_conncache_add_conn(struct conncache *connc,
|
||||
struct connectdata *conn) WARN_UNUSED_RESULT;
|
||||
void Curl_conncache_remove_conn(struct Curl_easy *data,
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2020, 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
|
||||
@ -75,6 +75,8 @@
|
||||
#include "conncache.h"
|
||||
#include "multihandle.h"
|
||||
#include "system_win32.h"
|
||||
#include "quic.h"
|
||||
#include "socks.h"
|
||||
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
@ -165,7 +167,7 @@ tcpkeepalive(struct Curl_easy *data,
|
||||
static CURLcode
|
||||
singleipconnect(struct connectdata *conn,
|
||||
const Curl_addrinfo *ai, /* start connecting to this */
|
||||
curl_socket_t *sock);
|
||||
int sockindex); /* 0 or 1 among the temp ones */
|
||||
|
||||
/*
|
||||
* Curl_timeleft() returns the amount of milliseconds left allowed for the
|
||||
@ -368,6 +370,11 @@ static CURLcode bindlocal(struct connectdata *conn,
|
||||
infof(data, "Name '%s' family %i resolved to '%s' family %i\n",
|
||||
dev, af, myhost, h->addr->ai_family);
|
||||
Curl_resolv_unlock(data, h);
|
||||
if(af != h->addr->ai_family) {
|
||||
/* bad IP version combo, signal the caller to try another address
|
||||
family if available */
|
||||
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||
}
|
||||
done = 1;
|
||||
}
|
||||
else {
|
||||
@ -590,7 +597,7 @@ static CURLcode trynextip(struct connectdata *conn,
|
||||
}
|
||||
|
||||
if(ai) {
|
||||
result = singleipconnect(conn, ai, &conn->tempsock[tempindex]);
|
||||
result = singleipconnect(conn, ai, tempindex);
|
||||
if(result == CURLE_COULDNT_CONNECT) {
|
||||
ai = ai->ai_next;
|
||||
continue;
|
||||
@ -620,13 +627,10 @@ void Curl_persistconninfo(struct connectdata *conn)
|
||||
conn->data->info.conn_local_port = conn->local_port;
|
||||
}
|
||||
|
||||
UNITTEST bool getaddressinfo(struct sockaddr *sa, char *addr,
|
||||
long *port);
|
||||
|
||||
/* retrieves ip address and port from a sockaddr structure.
|
||||
note it calls Curl_inet_ntop which sets errno on fail, not SOCKERRNO. */
|
||||
UNITTEST bool getaddressinfo(struct sockaddr *sa, char *addr,
|
||||
long *port)
|
||||
bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen,
|
||||
char *addr, long *port)
|
||||
{
|
||||
struct sockaddr_in *si = NULL;
|
||||
#ifdef ENABLE_IPV6
|
||||
@ -634,6 +638,8 @@ UNITTEST bool getaddressinfo(struct sockaddr *sa, char *addr,
|
||||
#endif
|
||||
#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
|
||||
struct sockaddr_un *su = NULL;
|
||||
#else
|
||||
(void)salen;
|
||||
#endif
|
||||
|
||||
switch(sa->sa_family) {
|
||||
@ -659,8 +665,12 @@ UNITTEST bool getaddressinfo(struct sockaddr *sa, char *addr,
|
||||
#endif
|
||||
#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
|
||||
case AF_UNIX:
|
||||
su = (struct sockaddr_un*)sa;
|
||||
msnprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path);
|
||||
if(salen > (curl_socklen_t)sizeof(sa_family_t)) {
|
||||
su = (struct sockaddr_un*)sa;
|
||||
msnprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path);
|
||||
}
|
||||
else
|
||||
addr[0] = 0; /* socket with no name */
|
||||
*port = 0;
|
||||
return TRUE;
|
||||
#endif
|
||||
@ -678,8 +688,8 @@ UNITTEST bool getaddressinfo(struct sockaddr *sa, char *addr,
|
||||
connection */
|
||||
void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
|
||||
{
|
||||
if(conn->socktype == SOCK_DGRAM)
|
||||
/* there's no connection! */
|
||||
if(conn->transport != TRNSPRT_TCP)
|
||||
/* there's no TCP connection! */
|
||||
return;
|
||||
|
||||
#if defined(HAVE_GETPEERNAME) || defined(HAVE_GETSOCKNAME)
|
||||
@ -688,10 +698,11 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
|
||||
char buffer[STRERROR_LEN];
|
||||
struct Curl_sockaddr_storage ssrem;
|
||||
struct Curl_sockaddr_storage ssloc;
|
||||
curl_socklen_t len;
|
||||
curl_socklen_t plen;
|
||||
curl_socklen_t slen;
|
||||
#ifdef HAVE_GETPEERNAME
|
||||
len = sizeof(struct Curl_sockaddr_storage);
|
||||
if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) {
|
||||
plen = sizeof(struct Curl_sockaddr_storage);
|
||||
if(getpeername(sockfd, (struct sockaddr*) &ssrem, &plen)) {
|
||||
int error = SOCKERRNO;
|
||||
failf(data, "getpeername() failed with errno %d: %s",
|
||||
error, Curl_strerror(error, buffer, sizeof(buffer)));
|
||||
@ -699,9 +710,9 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_GETSOCKNAME
|
||||
len = sizeof(struct Curl_sockaddr_storage);
|
||||
slen = sizeof(struct Curl_sockaddr_storage);
|
||||
memset(&ssloc, 0, sizeof(ssloc));
|
||||
if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) {
|
||||
if(getsockname(sockfd, (struct sockaddr*) &ssloc, &slen)) {
|
||||
int error = SOCKERRNO;
|
||||
failf(data, "getsockname() failed with errno %d: %s",
|
||||
error, Curl_strerror(error, buffer, sizeof(buffer)));
|
||||
@ -709,8 +720,8 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_GETPEERNAME
|
||||
if(!getaddressinfo((struct sockaddr*)&ssrem,
|
||||
conn->primary_ip, &conn->primary_port)) {
|
||||
if(!Curl_addr2string((struct sockaddr*)&ssrem, plen,
|
||||
conn->primary_ip, &conn->primary_port)) {
|
||||
failf(data, "ssrem inet_ntop() failed with errno %d: %s",
|
||||
errno, Curl_strerror(errno, buffer, sizeof(buffer)));
|
||||
return;
|
||||
@ -718,8 +729,8 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
|
||||
memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
|
||||
#endif
|
||||
#ifdef HAVE_GETSOCKNAME
|
||||
if(!getaddressinfo((struct sockaddr*)&ssloc,
|
||||
conn->local_ip, &conn->local_port)) {
|
||||
if(!Curl_addr2string((struct sockaddr*)&ssloc, slen,
|
||||
conn->local_ip, &conn->local_port)) {
|
||||
failf(data, "ssloc inet_ntop() failed with errno %d: %s",
|
||||
errno, Curl_strerror(errno, buffer, sizeof(buffer)));
|
||||
return;
|
||||
@ -734,6 +745,79 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
|
||||
Curl_persistconninfo(conn);
|
||||
}
|
||||
|
||||
/* After a TCP connection to the proxy has been verified, this function does
|
||||
the next magic steps. If 'done' isn't set TRUE, it is not done yet and
|
||||
must be called again.
|
||||
|
||||
Note: this function's sub-functions call failf()
|
||||
|
||||
*/
|
||||
static CURLcode connect_SOCKS(struct connectdata *conn, int sockindex,
|
||||
bool *done)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
if(conn->bits.socksproxy) {
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
/* for the secondary socket (FTP), use the "connect to host"
|
||||
* but ignore the "connect to port" (use the secondary port)
|
||||
*/
|
||||
const char * const host =
|
||||
conn->bits.httpproxy ?
|
||||
conn->http_proxy.host.name :
|
||||
conn->bits.conn_to_host ?
|
||||
conn->conn_to_host.name :
|
||||
sockindex == SECONDARYSOCKET ?
|
||||
conn->secondaryhostname : conn->host.name;
|
||||
const int port =
|
||||
conn->bits.httpproxy ? (int)conn->http_proxy.port :
|
||||
sockindex == SECONDARYSOCKET ? conn->secondary_port :
|
||||
conn->bits.conn_to_port ? conn->conn_to_port :
|
||||
conn->remote_port;
|
||||
switch(conn->socks_proxy.proxytype) {
|
||||
case CURLPROXY_SOCKS5:
|
||||
case CURLPROXY_SOCKS5_HOSTNAME:
|
||||
result = Curl_SOCKS5(conn->socks_proxy.user, conn->socks_proxy.passwd,
|
||||
host, port, sockindex, conn, done);
|
||||
break;
|
||||
|
||||
case CURLPROXY_SOCKS4:
|
||||
case CURLPROXY_SOCKS4A:
|
||||
result = Curl_SOCKS4(conn->socks_proxy.user, host, port, sockindex,
|
||||
conn, done);
|
||||
break;
|
||||
|
||||
default:
|
||||
failf(conn->data, "unknown proxytype option given");
|
||||
result = CURLE_COULDNT_CONNECT;
|
||||
} /* switch proxytype */
|
||||
#else
|
||||
(void)sockindex;
|
||||
#endif /* CURL_DISABLE_PROXY */
|
||||
}
|
||||
else
|
||||
*done = TRUE; /* no SOCKS proxy, so consider us connected */
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* post_SOCKS() is called after a successful connect to the peer, which
|
||||
* *could* be a SOCKS proxy
|
||||
*/
|
||||
static void post_SOCKS(struct connectdata *conn,
|
||||
int sockindex,
|
||||
bool *connected)
|
||||
{
|
||||
conn->bits.tcpconnect[sockindex] = TRUE;
|
||||
|
||||
*connected = TRUE;
|
||||
if(sockindex == FIRSTSOCKET)
|
||||
Curl_pgrsTime(conn->data, TIMER_CONNECT); /* connect done */
|
||||
Curl_updateconninfo(conn, conn->sock[sockindex]);
|
||||
Curl_verboseconnect(conn);
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_is_connected() checks if the socket has connected.
|
||||
*/
|
||||
@ -771,11 +855,37 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
||||
return CURLE_OPERATION_TIMEDOUT;
|
||||
}
|
||||
|
||||
if(SOCKS_STATE(conn->cnnct.state)) {
|
||||
/* still doing SOCKS */
|
||||
result = connect_SOCKS(conn, sockindex, connected);
|
||||
if(!result && *connected)
|
||||
post_SOCKS(conn, sockindex, connected);
|
||||
return result;
|
||||
}
|
||||
|
||||
for(i = 0; i<2; i++) {
|
||||
const int other = i ^ 1;
|
||||
if(conn->tempsock[i] == CURL_SOCKET_BAD)
|
||||
continue;
|
||||
|
||||
#ifdef ENABLE_QUIC
|
||||
if(conn->transport == TRNSPRT_QUIC) {
|
||||
result = Curl_quic_is_connected(conn, i, connected);
|
||||
if(result) {
|
||||
error = SOCKERRNO;
|
||||
goto error;
|
||||
}
|
||||
if(*connected) {
|
||||
/* use this socket from now on */
|
||||
conn->sock[sockindex] = conn->tempsock[i];
|
||||
conn->ip_addr = conn->tempaddr[i];
|
||||
conn->tempsock[i] = CURL_SOCKET_BAD;
|
||||
connkeep(conn, "HTTP/3 default");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef mpeix
|
||||
/* Call this function once now, and ignore the results. We do this to
|
||||
"clear" the error state on the socket so that we can later read it
|
||||
@ -789,8 +899,8 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
||||
if(rc == 0) { /* no connection yet */
|
||||
error = 0;
|
||||
if(Curl_timediff(now, conn->connecttime) >= conn->timeoutms_per_addr) {
|
||||
infof(data, "After %ldms connect time, move on!\n",
|
||||
conn->timeoutms_per_addr);
|
||||
infof(data, "After %" CURL_FORMAT_TIMEDIFF_T
|
||||
"ms connect time, move on!\n", conn->timeoutms_per_addr);
|
||||
error = ETIMEDOUT;
|
||||
}
|
||||
|
||||
@ -819,18 +929,13 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
||||
conn->tempsock[other] = CURL_SOCKET_BAD;
|
||||
}
|
||||
|
||||
/* see if we need to do any proxy magic first once we connected */
|
||||
result = Curl_connected_proxy(conn, sockindex);
|
||||
if(result)
|
||||
/* see if we need to kick off any SOCKS proxy magic once we
|
||||
connected */
|
||||
result = connect_SOCKS(conn, sockindex, connected);
|
||||
if(result || !*connected)
|
||||
return result;
|
||||
|
||||
conn->bits.tcpconnect[sockindex] = TRUE;
|
||||
|
||||
*connected = TRUE;
|
||||
if(sockindex == FIRSTSOCKET)
|
||||
Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
|
||||
Curl_updateconninfo(conn, conn->sock[sockindex]);
|
||||
Curl_verboseconnect(conn);
|
||||
post_SOCKS(conn, sockindex, connected);
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
@ -839,6 +944,9 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
||||
else if(rc & CURL_CSELECT_ERR)
|
||||
(void)verifyconnect(conn->tempsock[i], &error);
|
||||
|
||||
#ifdef ENABLE_QUIC
|
||||
error:
|
||||
#endif
|
||||
/*
|
||||
* The connection failed here, we should attempt to connect to the "next
|
||||
* address" for the given host. But first remember the latest error.
|
||||
@ -848,19 +956,21 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
||||
SET_SOCKERRNO(error);
|
||||
if(conn->tempaddr[i]) {
|
||||
CURLcode status;
|
||||
#ifndef CURL_DISABLE_VERBOSE_STRINGS
|
||||
char ipaddress[MAX_IPADR_LEN];
|
||||
char buffer[STRERROR_LEN];
|
||||
Curl_printable_address(conn->tempaddr[i], ipaddress, MAX_IPADR_LEN);
|
||||
#endif
|
||||
infof(data, "connect to %s port %ld failed: %s\n",
|
||||
ipaddress, conn->port,
|
||||
Curl_strerror(error, buffer, sizeof(buffer)));
|
||||
|
||||
conn->timeoutms_per_addr = conn->tempaddr[i]->ai_next == NULL ?
|
||||
allow : allow / 2;
|
||||
allow : allow / 2;
|
||||
|
||||
status = trynextip(conn, sockindex, i);
|
||||
if(status != CURLE_COULDNT_CONNECT
|
||||
|| conn->tempsock[other] == CURL_SOCKET_BAD)
|
||||
if((status != CURLE_COULDNT_CONNECT) ||
|
||||
conn->tempsock[other] == CURL_SOCKET_BAD)
|
||||
/* the last attempt failed and no other sockets remain open */
|
||||
result = status;
|
||||
}
|
||||
@ -892,6 +1002,14 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
||||
failf(data, "Failed to connect to %s port %ld: %s",
|
||||
hostname, conn->port,
|
||||
Curl_strerror(error, buffer, sizeof(buffer)));
|
||||
|
||||
#ifdef WSAETIMEDOUT
|
||||
if(WSAETIMEDOUT == data->state.os_errno)
|
||||
result = CURLE_OPERATION_TIMEDOUT;
|
||||
#elif defined(ETIMEDOUT)
|
||||
if(ETIMEDOUT == data->state.os_errno)
|
||||
result = CURLE_OPERATION_TIMEDOUT;
|
||||
#endif
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -900,14 +1018,12 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
||||
static void tcpnodelay(struct connectdata *conn, curl_socket_t sockfd)
|
||||
{
|
||||
#if defined(TCP_NODELAY)
|
||||
#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
struct Curl_easy *data = conn->data;
|
||||
#endif
|
||||
curl_socklen_t onoff = (curl_socklen_t) 1;
|
||||
int level = IPPROTO_TCP;
|
||||
#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
struct Curl_easy *data = conn->data;
|
||||
char buffer[STRERROR_LEN];
|
||||
|
||||
#if defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
#else
|
||||
(void) conn;
|
||||
#endif
|
||||
|
||||
@ -915,8 +1031,6 @@ static void tcpnodelay(struct connectdata *conn, curl_socket_t sockfd)
|
||||
sizeof(onoff)) < 0)
|
||||
infof(data, "Could not set TCP_NODELAY: %s\n",
|
||||
Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
|
||||
else
|
||||
infof(data, "TCP_NODELAY set\n");
|
||||
#else
|
||||
(void)conn;
|
||||
(void)sockfd;
|
||||
@ -999,7 +1113,7 @@ void Curl_sndbufset(curl_socket_t sockfd)
|
||||
*/
|
||||
static CURLcode singleipconnect(struct connectdata *conn,
|
||||
const Curl_addrinfo *ai,
|
||||
curl_socket_t *sockp)
|
||||
int sockindex)
|
||||
{
|
||||
struct Curl_sockaddr_ex addr;
|
||||
int rc = -1;
|
||||
@ -1015,7 +1129,7 @@ static CURLcode singleipconnect(struct connectdata *conn,
|
||||
int optval = 1;
|
||||
#endif
|
||||
char buffer[STRERROR_LEN];
|
||||
|
||||
curl_socket_t *sockp = &conn->tempsock[sockindex];
|
||||
*sockp = CURL_SOCKET_BAD;
|
||||
|
||||
result = Curl_socket(conn, ai, &addr, &sockfd);
|
||||
@ -1026,8 +1140,8 @@ static CURLcode singleipconnect(struct connectdata *conn,
|
||||
return CURLE_OK;
|
||||
|
||||
/* store remote address and port used in this connection attempt */
|
||||
if(!getaddressinfo((struct sockaddr*)&addr.sa_addr,
|
||||
ipaddress, &port)) {
|
||||
if(!Curl_addr2string((struct sockaddr*)&addr.sa_addr, addr.addrlen,
|
||||
ipaddress, &port)) {
|
||||
/* malformed address or bug in inet_ntop, try next address */
|
||||
failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
|
||||
errno, Curl_strerror(errno, buffer, sizeof(buffer)));
|
||||
@ -1094,8 +1208,8 @@ static CURLcode singleipconnect(struct connectdata *conn,
|
||||
if(conn->num_addr > 1)
|
||||
Curl_expire(data, conn->timeoutms_per_addr, EXPIRE_DNS_PER_NAME);
|
||||
|
||||
/* Connect TCP sockets, bind UDP */
|
||||
if(!isconnected && (conn->socktype == SOCK_STREAM)) {
|
||||
/* Connect TCP and QUIC sockets */
|
||||
if(!isconnected && (conn->transport != TRNSPRT_UDP)) {
|
||||
if(conn->bits.tcp_fastopen) {
|
||||
#if defined(CONNECT_DATA_IDEMPOTENT) /* Darwin */
|
||||
# if defined(HAVE_BUILTIN_AVAILABLE)
|
||||
@ -1124,8 +1238,6 @@ static CURLcode singleipconnect(struct connectdata *conn,
|
||||
if(setsockopt(sockfd, IPPROTO_TCP, TCP_FASTOPEN_CONNECT,
|
||||
(void *)&optval, sizeof(optval)) < 0)
|
||||
infof(data, "Failed to enable TCP Fast Open on fd %d\n", sockfd);
|
||||
else
|
||||
infof(data, "TCP_FASTOPEN_CONNECT set\n");
|
||||
|
||||
rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
|
||||
#elif defined(MSG_FASTOPEN) /* old Linux */
|
||||
@ -1141,6 +1253,16 @@ static CURLcode singleipconnect(struct connectdata *conn,
|
||||
|
||||
if(-1 == rc)
|
||||
error = SOCKERRNO;
|
||||
#ifdef ENABLE_QUIC
|
||||
else if(conn->transport == TRNSPRT_QUIC) {
|
||||
/* pass in 'sockfd' separately since it hasn't been put into the
|
||||
tempsock array at this point */
|
||||
result = Curl_quic_connect(conn, sockfd, sockindex,
|
||||
&addr.sa_addr, addr.addrlen);
|
||||
if(result)
|
||||
error = SOCKERRNO;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
*sockp = sockfd;
|
||||
@ -1214,7 +1336,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
||||
|
||||
/* start connecting to first IP */
|
||||
while(conn->tempaddr[0]) {
|
||||
result = singleipconnect(conn, conn->tempaddr[0], &(conn->tempsock[0]));
|
||||
result = singleipconnect(conn, conn->tempaddr[0], 0);
|
||||
if(!result)
|
||||
break;
|
||||
conn->tempaddr[0] = conn->tempaddr[0]->ai_next;
|
||||
@ -1326,12 +1448,11 @@ int Curl_closesocket(struct connectdata *conn,
|
||||
curl_socket_t sock)
|
||||
{
|
||||
if(conn && conn->fclosesocket) {
|
||||
if((sock == conn->sock[SECONDARYSOCKET]) &&
|
||||
conn->sock_accepted[SECONDARYSOCKET])
|
||||
if((sock == conn->sock[SECONDARYSOCKET]) && conn->sock_accepted)
|
||||
/* if this socket matches the second socket, and that was created with
|
||||
accept, then we MUST NOT call the callback but clear the accepted
|
||||
status */
|
||||
conn->sock_accepted[SECONDARYSOCKET] = FALSE;
|
||||
conn->sock_accepted = FALSE;
|
||||
else {
|
||||
int rc;
|
||||
Curl_multi_closed(conn->data, sock);
|
||||
@ -1381,8 +1502,9 @@ CURLcode Curl_socket(struct connectdata *conn,
|
||||
*/
|
||||
|
||||
addr->family = ai->ai_family;
|
||||
addr->socktype = conn->socktype;
|
||||
addr->protocol = conn->socktype == SOCK_DGRAM?IPPROTO_UDP:ai->ai_protocol;
|
||||
addr->socktype = (conn->transport == TRNSPRT_TCP) ? SOCK_STREAM : SOCK_DGRAM;
|
||||
addr->protocol = conn->transport != TRNSPRT_TCP ? IPPROTO_UDP :
|
||||
ai->ai_protocol;
|
||||
addr->addrlen = ai->ai_addrlen;
|
||||
|
||||
if(addr->addrlen > sizeof(struct Curl_sockaddr_storage))
|
||||
@ -1413,6 +1535,11 @@ CURLcode Curl_socket(struct connectdata *conn,
|
||||
/* no socket, no connection */
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
|
||||
if(conn->transport == TRNSPRT_QUIC) {
|
||||
/* QUIC sockets need to be nonblocking */
|
||||
(void)curlx_nonblock(*sockfd, TRUE);
|
||||
}
|
||||
|
||||
#if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
|
||||
if(conn->scope_id && (addr->family == AF_INET6)) {
|
||||
struct sockaddr_in6 * const sa6 = (void *)&addr->sa_addr;
|
||||
|
@ -51,6 +51,9 @@ timediff_t Curl_timeleft(struct Curl_easy *data,
|
||||
curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
|
||||
struct connectdata **connp);
|
||||
|
||||
bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen,
|
||||
char *addr, long *port);
|
||||
|
||||
/*
|
||||
* Check if a connection seems to be alive.
|
||||
*/
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2020, 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
|
||||
@ -96,6 +96,9 @@ Example set of cookies:
|
||||
#include "curl_get_line.h"
|
||||
#include "curl_memrchr.h"
|
||||
#include "inet_pton.h"
|
||||
#include "parsedate.h"
|
||||
#include "rand.h"
|
||||
#include "rename.h"
|
||||
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
@ -536,9 +539,9 @@ Curl_cookie_add(struct Curl_easy *data,
|
||||
* only test for names where that can possibly be true.
|
||||
*/
|
||||
if(nlen > 3 && name[0] == '_' && name[1] == '_') {
|
||||
if(strncasecompare("__Secure-", name, 9))
|
||||
if(!strncmp("__Secure-", name, 9))
|
||||
co->prefix |= COOKIE_PREFIX__SECURE;
|
||||
else if(strncasecompare("__Host-", name, 7))
|
||||
else if(!strncmp("__Host-", name, 7))
|
||||
co->prefix |= COOKIE_PREFIX__HOST;
|
||||
}
|
||||
|
||||
@ -715,7 +718,7 @@ Curl_cookie_add(struct Curl_easy *data,
|
||||
else if(co->expirestr) {
|
||||
/* Note that if the date couldn't get parsed for whatever reason,
|
||||
the cookie will be treated as a session cookie */
|
||||
co->expires = curl_getdate(co->expirestr, NULL);
|
||||
co->expires = Curl_getdate_capped(co->expirestr);
|
||||
|
||||
/* Session cookies have expires set to 0 so if we get that back
|
||||
from the date parser let's add a second to make it a
|
||||
@ -819,22 +822,14 @@ Curl_cookie_add(struct Curl_easy *data,
|
||||
badcookie = TRUE;
|
||||
break;
|
||||
case 1:
|
||||
/* This field got its explanation on the 23rd of May 2001 by
|
||||
Andrés García:
|
||||
|
||||
flag: A TRUE/FALSE value indicating if all machines within a given
|
||||
domain can access the variable. This value is set automatically by
|
||||
the browser, depending on the value you set for the domain.
|
||||
|
||||
As far as I can see, it is set to true when the cookie says
|
||||
/* flag: A TRUE/FALSE value indicating if all machines within a given
|
||||
domain can access the variable. Set TRUE when the cookie says
|
||||
.domain.com and to false when the domain is complete www.domain.com
|
||||
*/
|
||||
co->tailmatch = strcasecompare(ptr, "TRUE")?TRUE:FALSE;
|
||||
break;
|
||||
case 2:
|
||||
/* It turns out, that sometimes the file format allows the path
|
||||
field to remain not filled in, we try to detect this and work
|
||||
around it! Andrés García made us aware of this... */
|
||||
/* The file format allows the path field to remain not filled in */
|
||||
if(strcmp("TRUE", ptr) && strcmp("FALSE", ptr)) {
|
||||
/* only if the path doesn't look like a boolean option! */
|
||||
co->path = strdup(ptr);
|
||||
@ -1053,7 +1048,7 @@ Curl_cookie_add(struct Curl_easy *data,
|
||||
|
||||
*clist = *co; /* then store all the new data */
|
||||
|
||||
free(co); /* free the newly alloced memory */
|
||||
free(co); /* free the newly allocated memory */
|
||||
co = clist; /* point to the previous struct instead */
|
||||
|
||||
/* We have replaced a cookie, now skip the rest of the list but
|
||||
@ -1098,6 +1093,8 @@ Curl_cookie_add(struct Curl_easy *data,
|
||||
*
|
||||
* If 'newsession' is TRUE, discard all "session cookies" on read from file.
|
||||
*
|
||||
* Note that 'data' might be called as NULL pointer.
|
||||
*
|
||||
* Returns NULL on out of memory. Invalid cookies are ignored.
|
||||
****************************************************************************/
|
||||
struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
|
||||
@ -1168,6 +1165,8 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
|
||||
}
|
||||
|
||||
c->running = TRUE; /* now, we're running */
|
||||
if(data)
|
||||
data->state.cookie_engine = TRUE;
|
||||
|
||||
return c;
|
||||
|
||||
@ -1504,11 +1503,14 @@ static char *get_netscape_format(const struct Cookie *co)
|
||||
*
|
||||
* The function returns non-zero on write failure.
|
||||
*/
|
||||
static int cookie_output(struct CookieInfo *c, const char *dumphere)
|
||||
static int cookie_output(struct Curl_easy *data,
|
||||
struct CookieInfo *c, const char *filename)
|
||||
{
|
||||
struct Cookie *co;
|
||||
FILE *out;
|
||||
FILE *out = NULL;
|
||||
bool use_stdout = FALSE;
|
||||
char *tempstore = NULL;
|
||||
bool error = false;
|
||||
|
||||
if(!c)
|
||||
/* no cookie engine alive */
|
||||
@ -1517,16 +1519,24 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
|
||||
/* at first, remove expired cookies */
|
||||
remove_expired(c);
|
||||
|
||||
if(!strcmp("-", dumphere)) {
|
||||
if(!strcmp("-", filename)) {
|
||||
/* use stdout */
|
||||
out = stdout;
|
||||
use_stdout = TRUE;
|
||||
}
|
||||
else {
|
||||
out = fopen(dumphere, FOPEN_WRITETEXT);
|
||||
if(!out) {
|
||||
return 1; /* failure */
|
||||
}
|
||||
unsigned char randsuffix[9];
|
||||
|
||||
if(Curl_rand_hex(data, randsuffix, sizeof(randsuffix)))
|
||||
return 2;
|
||||
|
||||
tempstore = aprintf("%s.%s.tmp", filename, randsuffix);
|
||||
if(!tempstore)
|
||||
return 1;
|
||||
|
||||
out = fopen(tempstore, FOPEN_WRITETEXT);
|
||||
if(!out)
|
||||
goto error;
|
||||
}
|
||||
|
||||
fputs("# Netscape HTTP Cookie File\n"
|
||||
@ -1536,35 +1546,31 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
|
||||
|
||||
if(c->numcookies) {
|
||||
unsigned int i;
|
||||
unsigned int j;
|
||||
size_t nvalid = 0;
|
||||
struct Cookie **array;
|
||||
|
||||
array = malloc(sizeof(struct Cookie *) * c->numcookies);
|
||||
array = calloc(1, sizeof(struct Cookie *) * c->numcookies);
|
||||
if(!array) {
|
||||
if(!use_stdout)
|
||||
fclose(out);
|
||||
return 1;
|
||||
goto error;
|
||||
}
|
||||
|
||||
j = 0;
|
||||
/* only sort the cookies with a domain property */
|
||||
for(i = 0; i < COOKIE_HASH_SIZE; i++) {
|
||||
for(co = c->cookies[i]; co; co = co->next) {
|
||||
if(!co->domain)
|
||||
continue;
|
||||
array[j++] = co;
|
||||
array[nvalid++] = co;
|
||||
}
|
||||
}
|
||||
|
||||
qsort(array, c->numcookies, sizeof(struct Cookie *), cookie_sort_ct);
|
||||
qsort(array, nvalid, sizeof(struct Cookie *), cookie_sort_ct);
|
||||
|
||||
for(i = 0; i < j; i++) {
|
||||
for(i = 0; i < nvalid; i++) {
|
||||
char *format_ptr = get_netscape_format(array[i]);
|
||||
if(format_ptr == NULL) {
|
||||
fprintf(out, "#\n# Fatal libcurl error\n");
|
||||
free(array);
|
||||
if(!use_stdout)
|
||||
fclose(out);
|
||||
return 1;
|
||||
goto error;
|
||||
}
|
||||
fprintf(out, "%s\n", format_ptr);
|
||||
free(format_ptr);
|
||||
@ -1572,10 +1578,24 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
|
||||
|
||||
free(array);
|
||||
}
|
||||
if(!use_stdout)
|
||||
fclose(out);
|
||||
|
||||
return 0;
|
||||
if(!use_stdout) {
|
||||
fclose(out);
|
||||
out = NULL;
|
||||
if(Curl_rename(tempstore, filename)) {
|
||||
unlink(tempstore);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
goto cleanup;
|
||||
error:
|
||||
error = true;
|
||||
cleanup:
|
||||
if(out && !use_stdout)
|
||||
fclose(out);
|
||||
free(tempstore);
|
||||
return error ? 1 : 0;
|
||||
}
|
||||
|
||||
static struct curl_slist *cookie_list(struct Curl_easy *data)
|
||||
@ -1621,7 +1641,7 @@ struct curl_slist *Curl_cookie_list(struct Curl_easy *data)
|
||||
return list;
|
||||
}
|
||||
|
||||
void Curl_flush_cookies(struct Curl_easy *data, int cleanup)
|
||||
void Curl_flush_cookies(struct Curl_easy *data, bool cleanup)
|
||||
{
|
||||
if(data->set.str[STRING_COOKIEJAR]) {
|
||||
if(data->change.cookielist) {
|
||||
@ -1634,7 +1654,7 @@ void Curl_flush_cookies(struct Curl_easy *data, int cleanup)
|
||||
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
|
||||
|
||||
/* if we have a destination file for all the cookies to get dumped to */
|
||||
if(cookie_output(data->cookies, data->set.str[STRING_COOKIEJAR]))
|
||||
if(cookie_output(data, data->cookies, data->set.str[STRING_COOKIEJAR]))
|
||||
infof(data, "WARNING: failed to save cookies in %s\n",
|
||||
data->set.str[STRING_COOKIEJAR]);
|
||||
}
|
||||
@ -1650,6 +1670,7 @@ void Curl_flush_cookies(struct Curl_easy *data, int cleanup)
|
||||
|
||||
if(cleanup && (!data->share || (data->cookies != data->share->cookies))) {
|
||||
Curl_cookie_cleanup(data->cookies);
|
||||
data->cookies = NULL;
|
||||
}
|
||||
Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
|
||||
}
|
||||
|
@ -109,7 +109,7 @@ void Curl_cookie_clearsess(struct CookieInfo *cookies);
|
||||
#define Curl_cookie_cleanup(x) Curl_nop_stmt
|
||||
#define Curl_flush_cookies(x,y) Curl_nop_stmt
|
||||
#else
|
||||
void Curl_flush_cookies(struct Curl_easy *data, int cleanup);
|
||||
void Curl_flush_cookies(struct Curl_easy *data, bool cleanup);
|
||||
void Curl_cookie_cleanup(struct CookieInfo *);
|
||||
struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
|
||||
const char *, struct CookieInfo *, bool);
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2019, 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
|
||||
|
@ -64,6 +64,9 @@
|
||||
#define CURL_EXTERN_SYMBOL
|
||||
#endif
|
||||
|
||||
/* Allow SMB to work on Windows */
|
||||
#cmakedefine USE_WIN32_CRYPTO
|
||||
|
||||
/* Use Windows LDAP implementation */
|
||||
#cmakedefine USE_WIN32_LDAP 1
|
||||
|
||||
@ -139,9 +142,6 @@
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#cmakedefine HAVE_DLFCN_H 1
|
||||
|
||||
/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */
|
||||
#cmakedefine HAVE_ENGINE_LOAD_BUILTIN_ENGINES 1
|
||||
|
||||
/* Define to 1 if you have the <errno.h> header file. */
|
||||
#cmakedefine HAVE_ERRNO_H 1
|
||||
|
||||
@ -232,6 +232,9 @@
|
||||
/* Define to 1 if you have the `getsockname' function. */
|
||||
#cmakedefine HAVE_GETSOCKNAME 1
|
||||
|
||||
/* Define to 1 if you have the `if_nametoindex' function. */
|
||||
#cmakedefine HAVE_IF_NAMETOINDEX 1
|
||||
|
||||
/* Define to 1 if you have the `getpwuid' function. */
|
||||
#cmakedefine HAVE_GETPWUID 1
|
||||
|
||||
@ -395,9 +398,6 @@
|
||||
/* Define to 1 if you have the <libssh2.h> header file. */
|
||||
#cmakedefine HAVE_LIBSSH2_H 1
|
||||
|
||||
/* Define to 1 if you have the `ssl' library (-lssl). */
|
||||
#cmakedefine HAVE_LIBSSL 1
|
||||
|
||||
/* if zlib is available */
|
||||
#cmakedefine HAVE_LIBZ 1
|
||||
|
||||
@ -446,9 +446,6 @@
|
||||
/* Define to 1 if you have the <openssl/crypto.h> header file. */
|
||||
#cmakedefine HAVE_OPENSSL_CRYPTO_H 1
|
||||
|
||||
/* Define to 1 if you have the <openssl/engine.h> header file. */
|
||||
#cmakedefine HAVE_OPENSSL_ENGINE_H 1
|
||||
|
||||
/* Define to 1 if you have the <openssl/err.h> header file. */
|
||||
#cmakedefine HAVE_OPENSSL_ERR_H 1
|
||||
|
||||
@ -575,9 +572,6 @@
|
||||
/* Define to 1 if you have the `socket' function. */
|
||||
#cmakedefine HAVE_SOCKET 1
|
||||
|
||||
/* Define to 1 if you have the `SSL_get_shutdown' function. */
|
||||
#cmakedefine HAVE_SSL_GET_SHUTDOWN 1
|
||||
|
||||
/* Define to 1 if you have the <ssl.h> header file. */
|
||||
#cmakedefine HAVE_SSL_H 1
|
||||
|
||||
@ -879,35 +873,44 @@
|
||||
/* Define to the function return type for send. */
|
||||
#cmakedefine SEND_TYPE_RETV ${SEND_TYPE_RETV}
|
||||
|
||||
/*
|
||||
Note: SIZEOF_* variables are fetched with CMake through check_type_size().
|
||||
As per CMake documentation on CheckTypeSize, C preprocessor code is
|
||||
generated by CMake into SIZEOF_*_CODE. This is what we use in the
|
||||
following statements.
|
||||
|
||||
Reference: https://cmake.org/cmake/help/latest/module/CheckTypeSize.html
|
||||
*/
|
||||
|
||||
/* The size of `int', as computed by sizeof. */
|
||||
@SIZEOF_INT_CODE@
|
||||
${SIZEOF_INT_CODE}
|
||||
|
||||
/* The size of `short', as computed by sizeof. */
|
||||
@SIZEOF_SHORT_CODE@
|
||||
${SIZEOF_SHORT_CODE}
|
||||
|
||||
/* The size of `long', as computed by sizeof. */
|
||||
@SIZEOF_LONG_CODE@
|
||||
${SIZEOF_LONG_CODE}
|
||||
|
||||
/* The size of `long long', as computed by sizeof. */
|
||||
@SIZEOF_LONG_LONG_CODE@
|
||||
${SIZEOF_LONG_LONG_CODE}
|
||||
|
||||
/* The size of `__int64', as computed by sizeof. */
|
||||
@SIZEOF___INT64_CODE@
|
||||
${SIZEOF___INT64_CODE}
|
||||
|
||||
/* The size of `off_t', as computed by sizeof. */
|
||||
@SIZEOF_OFF_T_CODE@
|
||||
${SIZEOF_OFF_T_CODE}
|
||||
|
||||
/* The size of `curl_off_t', as computed by sizeof. */
|
||||
@SIZEOF_CURL_OFF_T_CODE@
|
||||
${SIZEOF_CURL_OFF_T_CODE}
|
||||
|
||||
/* The size of `size_t', as computed by sizeof. */
|
||||
@SIZEOF_SIZE_T_CODE@
|
||||
${SIZEOF_SIZE_T_CODE}
|
||||
|
||||
/* The size of `ssize_t', as computed by sizeof. */
|
||||
@SIZEOF_SSIZE_T_CODE@
|
||||
${SIZEOF_SSIZE_T_CODE}
|
||||
|
||||
/* The size of `time_t', as computed by sizeof. */
|
||||
@SIZEOF_TIME_T_CODE@
|
||||
${SIZEOF_TIME_T_CODE}
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#cmakedefine STDC_HEADERS 1
|
||||
@ -933,15 +936,15 @@
|
||||
/* if GnuTLS is enabled */
|
||||
#cmakedefine USE_GNUTLS 1
|
||||
|
||||
/* if PolarSSL is enabled */
|
||||
#cmakedefine USE_POLARSSL 1
|
||||
|
||||
/* if Secure Transport is enabled */
|
||||
#cmakedefine USE_SECTRANSP 1
|
||||
|
||||
/* if mbedTLS is enabled */
|
||||
#cmakedefine USE_MBEDTLS 1
|
||||
|
||||
/* if BearSSL is enabled */
|
||||
#cmakedefine USE_BEARSSL 1
|
||||
|
||||
/* if libSSH2 is in use */
|
||||
#cmakedefine USE_LIBSSH2 1
|
||||
|
||||
@ -951,6 +954,9 @@
|
||||
/* 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
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2015, Steve Holme, <steve_holme@hotmail.com>.
|
||||
* Copyright (C) 2015 - 2019, Steve Holme, <steve_holme@hotmail.com>.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2015, Steve Holme, <steve_holme@hotmail.com>.
|
||||
* Copyright (C) 2015 - 2019, Steve Holme, <steve_holme@hotmail.com>.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
|
@ -81,6 +81,7 @@ unsigned short Curl_read16_be(const unsigned char *buf)
|
||||
((unsigned short)buf[1]));
|
||||
}
|
||||
|
||||
#if (CURL_SIZEOF_CURL_OFF_T > 4)
|
||||
/*
|
||||
* write32_le()
|
||||
*
|
||||
@ -100,7 +101,6 @@ static void write32_le(const int value, unsigned char *buffer)
|
||||
buffer[3] = (char)((value & 0xFF000000) >> 24);
|
||||
}
|
||||
|
||||
#if (CURL_SIZEOF_CURL_OFF_T > 4)
|
||||
/*
|
||||
* Curl_write64_le()
|
||||
*
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2019, 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
|
||||
@ -31,9 +31,6 @@ unsigned int Curl_read32_le(const unsigned char *buf);
|
||||
/* Converts a 16-bit integer from big endian */
|
||||
unsigned short Curl_read16_be(const unsigned char *buf);
|
||||
|
||||
/* Converts a 32-bit integer to little endian */
|
||||
void Curl_write32_le(const int value, unsigned char *buffer);
|
||||
|
||||
#if (CURL_SIZEOF_CURL_OFF_T > 4)
|
||||
/* Converts a 64-bit integer to little endian */
|
||||
#if defined(HAVE_LONGLONG)
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2019, 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
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2019, 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
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2020, 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
|
||||
@ -24,6 +24,8 @@
|
||||
|
||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||
|
||||
#define HMAC_MD5_LENGTH 16
|
||||
|
||||
typedef void (* HMAC_hinit_func)(void *context);
|
||||
typedef void (* HMAC_hupdate_func)(void *context,
|
||||
const unsigned char *data,
|
||||
@ -62,6 +64,11 @@ int Curl_HMAC_update(HMAC_context *context,
|
||||
unsigned int len);
|
||||
int Curl_HMAC_final(HMAC_context *context, unsigned char *result);
|
||||
|
||||
CURLcode Curl_hmacit(const HMAC_params *hashparams,
|
||||
const unsigned char *key, const size_t keylen,
|
||||
const unsigned char *data, const size_t datalen,
|
||||
unsigned char *output);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* HEADER_CURL_HMAC_H */
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2019, 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
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2020, 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
|
||||
@ -24,14 +24,13 @@
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#if defined(USE_NSS) || defined(USE_OS400CRYPTO) || \
|
||||
(defined(USE_OPENSSL) && defined(OPENSSL_NO_MD4)) || \
|
||||
(defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C))
|
||||
#if !defined(CURL_DISABLE_CRYPTO_AUTH)
|
||||
|
||||
void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len);
|
||||
#define MD4_DIGEST_LENGTH 16
|
||||
|
||||
#endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) ||
|
||||
(defined(USE_OPENSSL) && defined(OPENSSL_NO_MD4)) ||
|
||||
(defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C)) */
|
||||
void Curl_md4it(unsigned char *output, const unsigned char *input,
|
||||
const size_t len);
|
||||
|
||||
#endif /* !defined(CURL_DISABLE_CRYPTO_AUTH) */
|
||||
|
||||
#endif /* HEADER_CURL_MD4_H */
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2020, 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
|
||||
@ -49,8 +49,8 @@ typedef struct {
|
||||
extern const MD5_params Curl_DIGEST_MD5[1];
|
||||
extern const HMAC_params Curl_HMAC_MD5[1];
|
||||
|
||||
void Curl_md5it(unsigned char *output,
|
||||
const unsigned char *input);
|
||||
void Curl_md5it(unsigned char *output, const unsigned char *input,
|
||||
const size_t len);
|
||||
|
||||
MD5_context * Curl_MD5_init(const MD5_params *md5params);
|
||||
CURLcode Curl_MD5_update(MD5_context *context,
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2019, 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
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2019, 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
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2019, 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
|
||||
@ -61,8 +61,13 @@ char *Curl_convert_wchar_to_UTF8(const wchar_t *str_w);
|
||||
|
||||
#define Curl_convert_UTF8_to_tchar(ptr) Curl_convert_UTF8_to_wchar((ptr))
|
||||
#define Curl_convert_tchar_to_UTF8(ptr) Curl_convert_wchar_to_UTF8((ptr))
|
||||
#define Curl_unicodefree(ptr) \
|
||||
do {if((ptr)) {free((ptr)); (ptr) = NULL;}} WHILE_FALSE
|
||||
#define Curl_unicodefree(ptr) \
|
||||
do { \
|
||||
if(ptr) { \
|
||||
free(ptr); \
|
||||
(ptr) = NULL; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
typedef union {
|
||||
unsigned short *tchar_ptr;
|
||||
@ -76,7 +81,7 @@ typedef union {
|
||||
#define Curl_convert_UTF8_to_tchar(ptr) (ptr)
|
||||
#define Curl_convert_tchar_to_UTF8(ptr) (ptr)
|
||||
#define Curl_unicodefree(ptr) \
|
||||
do {(ptr) = NULL;} WHILE_FALSE
|
||||
do {(ptr) = NULL;} while(0)
|
||||
|
||||
typedef union {
|
||||
char *tchar_ptr;
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2020, 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
|
||||
@ -55,11 +55,6 @@
|
||||
#ifdef USE_OPENSSL
|
||||
|
||||
# include <openssl/des.h>
|
||||
# ifndef OPENSSL_NO_MD4
|
||||
# include <openssl/md4.h>
|
||||
# else
|
||||
# include "curl_md4.h"
|
||||
# endif
|
||||
# include <openssl/md5.h>
|
||||
# include <openssl/ssl.h>
|
||||
# include <openssl/rand.h>
|
||||
@ -79,29 +74,23 @@
|
||||
#elif defined(USE_GNUTLS_NETTLE)
|
||||
|
||||
# include <nettle/des.h>
|
||||
# include <nettle/md4.h>
|
||||
|
||||
#elif defined(USE_GNUTLS)
|
||||
|
||||
# include <gcrypt.h>
|
||||
# define MD5_DIGEST_LENGTH 16
|
||||
# define MD4_DIGEST_LENGTH 16
|
||||
|
||||
#elif defined(USE_NSS)
|
||||
|
||||
# include <nss.h>
|
||||
# include <pk11pub.h>
|
||||
# include <hasht.h>
|
||||
# include "curl_md4.h"
|
||||
# define MD5_DIGEST_LENGTH MD5_LENGTH
|
||||
|
||||
#elif defined(USE_MBEDTLS)
|
||||
|
||||
# include <mbedtls/des.h>
|
||||
# include <mbedtls/md4.h>
|
||||
# if !defined(MBEDTLS_MD4_C)
|
||||
# include "curl_md4.h"
|
||||
# endif
|
||||
# include "curl_md4.h"
|
||||
|
||||
#elif defined(USE_SECTRANSP)
|
||||
|
||||
@ -110,7 +99,6 @@
|
||||
|
||||
#elif defined(USE_OS400CRYPTO)
|
||||
# include "cipher.mih" /* mih/cipher */
|
||||
# include "curl_md4.h"
|
||||
#elif defined(USE_WIN32_CRYPTO)
|
||||
# include <wincrypt.h>
|
||||
#else
|
||||
@ -126,12 +114,12 @@
|
||||
#include "warnless.h"
|
||||
#include "curl_endian.h"
|
||||
#include "curl_des.h"
|
||||
#include "curl_md4.h"
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
#define NTLM_HMAC_MD5_LEN (16)
|
||||
#define NTLMv2_BLOB_SIGNATURE "\x01\x01\x00\x00"
|
||||
#define NTLMv2_BLOB_LEN (44 -16 + ntlm->target_info_len + 4)
|
||||
|
||||
@ -218,7 +206,6 @@ 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 */
|
||||
PK11SlotInfo *slot = NULL;
|
||||
char key[8]; /* expanded 64 bit key */
|
||||
SECItem key_item;
|
||||
PK11SymKey *symkey = NULL;
|
||||
@ -228,7 +215,7 @@ static bool encrypt_des(const unsigned char *in, unsigned char *out,
|
||||
bool rv = FALSE;
|
||||
|
||||
/* use internal slot for DES encryption (requires NSS to be initialized) */
|
||||
slot = PK11_GetInternalKeySlot();
|
||||
PK11SlotInfo *slot = PK11_GetInternalKeySlot();
|
||||
if(!slot)
|
||||
return FALSE;
|
||||
|
||||
@ -553,7 +540,7 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data,
|
||||
CURLcode result;
|
||||
if(len > SIZE_T_MAX/2) /* avoid integer overflow */
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
pw = len ? malloc(len * 2) : strdup("");
|
||||
pw = len ? malloc(len * 2) : (unsigned char *)strdup("");
|
||||
if(!pw)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
@ -567,57 +554,10 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data,
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
{
|
||||
/* Create NT hashed password. */
|
||||
#ifdef USE_OPENSSL
|
||||
#if !defined(OPENSSL_NO_MD4)
|
||||
MD4_CTX MD4pw;
|
||||
MD4_Init(&MD4pw);
|
||||
MD4_Update(&MD4pw, pw, 2 * len);
|
||||
MD4_Final(ntbuffer, &MD4pw);
|
||||
#else
|
||||
Curl_md4it(ntbuffer, pw, 2 * len);
|
||||
#endif
|
||||
#elif defined(USE_GNUTLS_NETTLE)
|
||||
struct md4_ctx MD4pw;
|
||||
md4_init(&MD4pw);
|
||||
md4_update(&MD4pw, (unsigned int)(2 * len), pw);
|
||||
md4_digest(&MD4pw, MD4_DIGEST_SIZE, ntbuffer);
|
||||
#elif defined(USE_GNUTLS)
|
||||
gcry_md_hd_t MD4pw;
|
||||
gcry_md_open(&MD4pw, GCRY_MD_MD4, 0);
|
||||
gcry_md_write(MD4pw, pw, 2 * len);
|
||||
memcpy(ntbuffer, gcry_md_read(MD4pw, 0), MD4_DIGEST_LENGTH);
|
||||
gcry_md_close(MD4pw);
|
||||
#elif defined(USE_NSS)
|
||||
Curl_md4it(ntbuffer, pw, 2 * len);
|
||||
#elif defined(USE_MBEDTLS)
|
||||
#if defined(MBEDTLS_MD4_C)
|
||||
mbedtls_md4(pw, 2 * len, ntbuffer);
|
||||
#else
|
||||
Curl_md4it(ntbuffer, pw, 2 * len);
|
||||
#endif
|
||||
#elif defined(USE_SECTRANSP)
|
||||
(void)CC_MD4(pw, (CC_LONG)(2 * len), ntbuffer);
|
||||
#elif defined(USE_OS400CRYPTO)
|
||||
Curl_md4it(ntbuffer, pw, 2 * len);
|
||||
#elif defined(USE_WIN32_CRYPTO)
|
||||
HCRYPTPROV hprov;
|
||||
if(CryptAcquireContext(&hprov, NULL, NULL, PROV_RSA_FULL,
|
||||
CRYPT_VERIFYCONTEXT)) {
|
||||
HCRYPTHASH hhash;
|
||||
if(CryptCreateHash(hprov, CALG_MD4, 0, 0, &hhash)) {
|
||||
DWORD length = 16;
|
||||
CryptHashData(hhash, pw, (unsigned int)len * 2, 0);
|
||||
CryptGetHashParam(hhash, HP_HASHVAL, ntbuffer, &length, 0);
|
||||
CryptDestroyHash(hhash);
|
||||
}
|
||||
CryptReleaseContext(hprov, 0);
|
||||
}
|
||||
#endif
|
||||
/* Create NT hashed password. */
|
||||
Curl_md4it(ntbuffer, pw, 2 * len);
|
||||
|
||||
memset(ntbuffer + 16, 0, 21 - 16);
|
||||
}
|
||||
memset(ntbuffer + 16, 0, 21 - 16);
|
||||
|
||||
free(pw);
|
||||
|
||||
@ -626,25 +566,6 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data,
|
||||
|
||||
#if defined(USE_NTLM_V2) && !defined(USE_WINDOWS_SSPI)
|
||||
|
||||
/* This returns the HMAC MD5 digest */
|
||||
static CURLcode hmac_md5(const unsigned char *key, unsigned int keylen,
|
||||
const unsigned char *data, unsigned int datalen,
|
||||
unsigned char *output)
|
||||
{
|
||||
HMAC_context *ctxt = Curl_HMAC_init(Curl_HMAC_MD5, key, keylen);
|
||||
|
||||
if(!ctxt)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
/* Update the digest with the given challenge */
|
||||
Curl_HMAC_update(ctxt, data, datalen);
|
||||
|
||||
/* Finalise the digest */
|
||||
Curl_HMAC_final(ctxt, output);
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/* This creates the NTLMv2 hash by using NTLM hash as the key and Unicode
|
||||
* (uppercase UserName + Domain) as the data
|
||||
*/
|
||||
@ -674,8 +595,8 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen,
|
||||
ascii_uppercase_to_unicode_le(identity, user, userlen);
|
||||
ascii_to_unicode_le(identity + (userlen << 1), domain, domlen);
|
||||
|
||||
result = hmac_md5(ntlmhash, 16, identity, curlx_uztoui(identity_len),
|
||||
ntlmv2hash);
|
||||
result = Curl_hmacit(Curl_HMAC_MD5, ntlmhash, 16, identity, identity_len,
|
||||
ntlmv2hash);
|
||||
free(identity);
|
||||
|
||||
return result;
|
||||
@ -721,7 +642,7 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
|
||||
|
||||
unsigned int len = 0;
|
||||
unsigned char *ptr = NULL;
|
||||
unsigned char hmac_output[NTLM_HMAC_MD5_LEN];
|
||||
unsigned char hmac_output[HMAC_MD5_LENGTH];
|
||||
curl_off_t tw;
|
||||
|
||||
CURLcode result = CURLE_OK;
|
||||
@ -740,7 +661,7 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
|
||||
tw = ((curl_off_t)time(NULL) + CURL_OFF_T_C(11644473600)) * 10000000;
|
||||
|
||||
/* Calculate the response len */
|
||||
len = NTLM_HMAC_MD5_LEN + NTLMv2_BLOB_LEN;
|
||||
len = HMAC_MD5_LENGTH + NTLMv2_BLOB_LEN;
|
||||
|
||||
/* Allocate the response */
|
||||
ptr = calloc(1, len);
|
||||
@ -748,7 +669,7 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
/* Create the BLOB structure */
|
||||
msnprintf((char *)ptr + NTLM_HMAC_MD5_LEN, NTLMv2_BLOB_LEN,
|
||||
msnprintf((char *)ptr + HMAC_MD5_LENGTH, NTLMv2_BLOB_LEN,
|
||||
"%c%c%c%c" /* NTLMv2_BLOB_SIGNATURE */
|
||||
"%c%c%c%c", /* Reserved = 0 */
|
||||
NTLMv2_BLOB_SIGNATURE[0], NTLMv2_BLOB_SIGNATURE[1],
|
||||
@ -761,7 +682,7 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
|
||||
|
||||
/* Concatenate the Type 2 challenge with the BLOB and do HMAC MD5 */
|
||||
memcpy(ptr + 8, &ntlm->nonce[0], 8);
|
||||
result = hmac_md5(ntlmv2hash, NTLM_HMAC_MD5_LEN, ptr + 8,
|
||||
result = Curl_hmacit(Curl_HMAC_MD5, ntlmv2hash, HMAC_MD5_LENGTH, ptr + 8,
|
||||
NTLMv2_BLOB_LEN + 8, hmac_output);
|
||||
if(result) {
|
||||
free(ptr);
|
||||
@ -769,7 +690,7 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
|
||||
}
|
||||
|
||||
/* Concatenate the HMAC MD5 output with the BLOB */
|
||||
memcpy(ptr, hmac_output, NTLM_HMAC_MD5_LEN);
|
||||
memcpy(ptr, hmac_output, HMAC_MD5_LENGTH);
|
||||
|
||||
/* Return the response */
|
||||
*ntresp = ptr;
|
||||
@ -804,7 +725,8 @@ CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash,
|
||||
memcpy(&data[0], challenge_server, 8);
|
||||
memcpy(&data[8], challenge_client, 8);
|
||||
|
||||
result = hmac_md5(ntlmv2hash, 16, &data[0], 16, hmac_output);
|
||||
result = Curl_hmacit(Curl_HMAC_MD5, ntlmv2hash, 16, &data[0], 16,
|
||||
hmac_output);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2020, 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
|
||||
@ -46,9 +46,9 @@
|
||||
#define USE_NTRESPONSES
|
||||
|
||||
/* Define USE_NTLM2SESSION in order to make the type-3 message include the
|
||||
NTLM2Session response message, requires USE_NTRESPONSES defined to 1 and a
|
||||
Crypto engine that we have curl_ssl_md5sum() for. */
|
||||
#if defined(USE_NTRESPONSES) && !defined(USE_WIN32_CRYPTO)
|
||||
NTLM2Session response message, requires USE_NTRESPONSES defined to 1 and
|
||||
MD5 support */
|
||||
#if defined(USE_NTRESPONSES) && !defined(CURL_DISABLE_CRYPTO_AUTH)
|
||||
#define USE_NTLM2SESSION
|
||||
#endif
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2020, 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
|
||||
@ -76,22 +76,22 @@
|
||||
# define sclose_nolog(x) close((x))
|
||||
#endif
|
||||
|
||||
void Curl_http_auth_cleanup_ntlm_wb(struct connectdata *conn)
|
||||
static void ntlm_wb_cleanup(struct ntlmdata *ntlm)
|
||||
{
|
||||
if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD) {
|
||||
sclose(conn->ntlm_auth_hlpr_socket);
|
||||
conn->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
|
||||
if(ntlm->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD) {
|
||||
sclose(ntlm->ntlm_auth_hlpr_socket);
|
||||
ntlm->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
|
||||
}
|
||||
|
||||
if(conn->ntlm_auth_hlpr_pid) {
|
||||
if(ntlm->ntlm_auth_hlpr_pid) {
|
||||
int i;
|
||||
for(i = 0; i < 4; i++) {
|
||||
pid_t ret = waitpid(conn->ntlm_auth_hlpr_pid, NULL, WNOHANG);
|
||||
if(ret == conn->ntlm_auth_hlpr_pid || errno == ECHILD)
|
||||
pid_t ret = waitpid(ntlm->ntlm_auth_hlpr_pid, NULL, WNOHANG);
|
||||
if(ret == ntlm->ntlm_auth_hlpr_pid || errno == ECHILD)
|
||||
break;
|
||||
switch(i) {
|
||||
case 0:
|
||||
kill(conn->ntlm_auth_hlpr_pid, SIGTERM);
|
||||
kill(ntlm->ntlm_auth_hlpr_pid, SIGTERM);
|
||||
break;
|
||||
case 1:
|
||||
/* Give the process another moment to shut down cleanly before
|
||||
@ -99,22 +99,21 @@ void Curl_http_auth_cleanup_ntlm_wb(struct connectdata *conn)
|
||||
Curl_wait_ms(1);
|
||||
break;
|
||||
case 2:
|
||||
kill(conn->ntlm_auth_hlpr_pid, SIGKILL);
|
||||
kill(ntlm->ntlm_auth_hlpr_pid, SIGKILL);
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
}
|
||||
}
|
||||
conn->ntlm_auth_hlpr_pid = 0;
|
||||
ntlm->ntlm_auth_hlpr_pid = 0;
|
||||
}
|
||||
|
||||
free(conn->challenge_header);
|
||||
conn->challenge_header = NULL;
|
||||
free(conn->response_header);
|
||||
conn->response_header = NULL;
|
||||
Curl_safefree(ntlm->challenge);
|
||||
Curl_safefree(ntlm->response);
|
||||
}
|
||||
|
||||
static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp)
|
||||
static CURLcode ntlm_wb_init(struct Curl_easy *data, struct ntlmdata *ntlm,
|
||||
const char *userp)
|
||||
{
|
||||
curl_socket_t sockfds[2];
|
||||
pid_t child_pid;
|
||||
@ -128,9 +127,13 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp)
|
||||
#endif
|
||||
char buffer[STRERROR_LEN];
|
||||
|
||||
#if defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
(void) data;
|
||||
#endif
|
||||
|
||||
/* Return if communication with ntlm_auth already set up */
|
||||
if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD ||
|
||||
conn->ntlm_auth_hlpr_pid)
|
||||
if(ntlm->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD ||
|
||||
ntlm->ntlm_auth_hlpr_pid)
|
||||
return CURLE_OK;
|
||||
|
||||
username = userp;
|
||||
@ -181,13 +184,13 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp)
|
||||
ntlm_auth = NTLM_WB_FILE;
|
||||
|
||||
if(access(ntlm_auth, X_OK) != 0) {
|
||||
failf(conn->data, "Could not access ntlm_auth: %s errno %d: %s",
|
||||
failf(data, "Could not access ntlm_auth: %s errno %d: %s",
|
||||
ntlm_auth, errno, Curl_strerror(errno, buffer, sizeof(buffer)));
|
||||
goto done;
|
||||
}
|
||||
|
||||
if(socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds)) {
|
||||
failf(conn->data, "Could not open socket pair. errno %d: %s",
|
||||
if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds)) {
|
||||
failf(data, "Could not open socket pair. errno %d: %s",
|
||||
errno, Curl_strerror(errno, buffer, sizeof(buffer)));
|
||||
goto done;
|
||||
}
|
||||
@ -196,7 +199,7 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp)
|
||||
if(child_pid == -1) {
|
||||
sclose(sockfds[0]);
|
||||
sclose(sockfds[1]);
|
||||
failf(conn->data, "Could not fork. errno %d: %s",
|
||||
failf(data, "Could not fork. errno %d: %s",
|
||||
errno, Curl_strerror(errno, buffer, sizeof(buffer)));
|
||||
goto done;
|
||||
}
|
||||
@ -208,13 +211,13 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp)
|
||||
/* Don't use sclose in the child since it fools the socket leak detector */
|
||||
sclose_nolog(sockfds[0]);
|
||||
if(dup2(sockfds[1], STDIN_FILENO) == -1) {
|
||||
failf(conn->data, "Could not redirect child stdin. errno %d: %s",
|
||||
failf(data, "Could not redirect child stdin. errno %d: %s",
|
||||
errno, Curl_strerror(errno, buffer, sizeof(buffer)));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(dup2(sockfds[1], STDOUT_FILENO) == -1) {
|
||||
failf(conn->data, "Could not redirect child stdout. errno %d: %s",
|
||||
failf(data, "Could not redirect child stdout. errno %d: %s",
|
||||
errno, Curl_strerror(errno, buffer, sizeof(buffer)));
|
||||
exit(1);
|
||||
}
|
||||
@ -234,14 +237,14 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp)
|
||||
NULL);
|
||||
|
||||
sclose_nolog(sockfds[1]);
|
||||
failf(conn->data, "Could not execl(). errno %d: %s",
|
||||
failf(data, "Could not execl(). errno %d: %s",
|
||||
errno, Curl_strerror(errno, buffer, sizeof(buffer)));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
sclose(sockfds[1]);
|
||||
conn->ntlm_auth_hlpr_socket = sockfds[0];
|
||||
conn->ntlm_auth_hlpr_pid = child_pid;
|
||||
ntlm->ntlm_auth_hlpr_socket = sockfds[0];
|
||||
ntlm->ntlm_auth_hlpr_pid = child_pid;
|
||||
free(domain);
|
||||
free(ntlm_auth_alloc);
|
||||
return CURLE_OK;
|
||||
@ -255,17 +258,21 @@ done:
|
||||
/* if larger than this, something is seriously wrong */
|
||||
#define MAX_NTLM_WB_RESPONSE 100000
|
||||
|
||||
static CURLcode ntlm_wb_response(struct connectdata *conn,
|
||||
static CURLcode ntlm_wb_response(struct Curl_easy *data, struct ntlmdata *ntlm,
|
||||
const char *input, curlntlm state)
|
||||
{
|
||||
char *buf = malloc(NTLM_BUFSIZE);
|
||||
size_t len_in = strlen(input), len_out = 0;
|
||||
|
||||
#if defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
(void) data;
|
||||
#endif
|
||||
|
||||
if(!buf)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
while(len_in > 0) {
|
||||
ssize_t written = swrite(conn->ntlm_auth_hlpr_socket, input, len_in);
|
||||
ssize_t written = swrite(ntlm->ntlm_auth_hlpr_socket, input, len_in);
|
||||
if(written == -1) {
|
||||
/* Interrupted by a signal, retry it */
|
||||
if(errno == EINTR)
|
||||
@ -281,7 +288,7 @@ static CURLcode ntlm_wb_response(struct connectdata *conn,
|
||||
ssize_t size;
|
||||
char *newbuf;
|
||||
|
||||
size = sread(conn->ntlm_auth_hlpr_socket, buf + len_out, NTLM_BUFSIZE);
|
||||
size = sread(ntlm->ntlm_auth_hlpr_socket, buf + len_out, NTLM_BUFSIZE);
|
||||
if(size == -1) {
|
||||
if(errno == EINTR)
|
||||
continue;
|
||||
@ -297,7 +304,7 @@ static CURLcode ntlm_wb_response(struct connectdata *conn,
|
||||
}
|
||||
|
||||
if(len_out > MAX_NTLM_WB_RESPONSE) {
|
||||
failf(conn->data, "too large ntlm_wb response!");
|
||||
failf(data, "too large ntlm_wb response!");
|
||||
free(buf);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
@ -325,9 +332,9 @@ static CURLcode ntlm_wb_response(struct connectdata *conn,
|
||||
(buf[0]!='A' || buf[1]!='F' || buf[2]!=' '))
|
||||
goto done;
|
||||
|
||||
conn->response_header = aprintf("NTLM %.*s", len_out - 4, buf + 3);
|
||||
ntlm->response = aprintf("%.*s", len_out - 4, buf + 3);
|
||||
free(buf);
|
||||
if(!conn->response_header)
|
||||
if(!ntlm->response)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
return CURLE_OK;
|
||||
done:
|
||||
@ -339,6 +346,7 @@ CURLcode Curl_input_ntlm_wb(struct connectdata *conn,
|
||||
bool proxy,
|
||||
const char *header)
|
||||
{
|
||||
struct ntlmdata *ntlm = proxy ? &conn->proxyntlm : &conn->ntlm;
|
||||
curlntlm *state = proxy ? &conn->proxy_ntlm_state : &conn->http_ntlm_state;
|
||||
|
||||
if(!checkprefix("NTLM", header))
|
||||
@ -349,8 +357,8 @@ CURLcode Curl_input_ntlm_wb(struct connectdata *conn,
|
||||
header++;
|
||||
|
||||
if(*header) {
|
||||
conn->challenge_header = strdup(header);
|
||||
if(!conn->challenge_header)
|
||||
ntlm->challenge = strdup(header);
|
||||
if(!ntlm->challenge)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
*state = NTLMSTATE_TYPE2; /* We got a type-2 message */
|
||||
@ -389,11 +397,11 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
|
||||
char **allocuserpwd;
|
||||
/* point to the name and password for this */
|
||||
const char *userp;
|
||||
struct ntlmdata *ntlm;
|
||||
curlntlm *state;
|
||||
struct auth *authp;
|
||||
|
||||
CURLcode res = CURLE_OK;
|
||||
char *input;
|
||||
|
||||
DEBUGASSERT(conn);
|
||||
DEBUGASSERT(conn->data);
|
||||
@ -401,12 +409,14 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
|
||||
if(proxy) {
|
||||
allocuserpwd = &conn->allocptr.proxyuserpwd;
|
||||
userp = conn->http_proxy.user;
|
||||
ntlm = &conn->proxyntlm;
|
||||
state = &conn->proxy_ntlm_state;
|
||||
authp = &conn->data->state.authproxy;
|
||||
}
|
||||
else {
|
||||
allocuserpwd = &conn->allocptr.userpwd;
|
||||
userp = conn->user;
|
||||
ntlm = &conn->ntlm;
|
||||
state = &conn->http_ntlm_state;
|
||||
authp = &conn->data->state.authhost;
|
||||
}
|
||||
@ -432,38 +442,36 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
|
||||
* request handling process.
|
||||
*/
|
||||
/* Create communication with ntlm_auth */
|
||||
res = ntlm_wb_init(conn, userp);
|
||||
res = ntlm_wb_init(conn->data, ntlm, userp);
|
||||
if(res)
|
||||
return res;
|
||||
res = ntlm_wb_response(conn, "YR\n", *state);
|
||||
res = ntlm_wb_response(conn->data, ntlm, "YR\n", *state);
|
||||
if(res)
|
||||
return res;
|
||||
|
||||
free(*allocuserpwd);
|
||||
*allocuserpwd = aprintf("%sAuthorization: %s\r\n",
|
||||
*allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
|
||||
proxy ? "Proxy-" : "",
|
||||
conn->response_header);
|
||||
ntlm->response);
|
||||
DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd));
|
||||
free(conn->response_header);
|
||||
Curl_safefree(ntlm->response);
|
||||
if(!*allocuserpwd)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
conn->response_header = NULL;
|
||||
break;
|
||||
|
||||
case NTLMSTATE_TYPE2:
|
||||
input = aprintf("TT %s\n", conn->challenge_header);
|
||||
case NTLMSTATE_TYPE2: {
|
||||
char *input = aprintf("TT %s\n", ntlm->challenge);
|
||||
if(!input)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
res = ntlm_wb_response(conn, input, *state);
|
||||
res = ntlm_wb_response(conn->data, ntlm, input, *state);
|
||||
free(input);
|
||||
input = NULL;
|
||||
if(res)
|
||||
return res;
|
||||
|
||||
free(*allocuserpwd);
|
||||
*allocuserpwd = aprintf("%sAuthorization: %s\r\n",
|
||||
*allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
|
||||
proxy ? "Proxy-" : "",
|
||||
conn->response_header);
|
||||
ntlm->response);
|
||||
DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd));
|
||||
*state = NTLMSTATE_TYPE3; /* we sent a type-3 */
|
||||
authp->done = TRUE;
|
||||
@ -471,7 +479,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
|
||||
if(!*allocuserpwd)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
break;
|
||||
|
||||
}
|
||||
case NTLMSTATE_TYPE3:
|
||||
/* connection is already authenticated,
|
||||
* don't send a header in future requests */
|
||||
@ -486,4 +494,10 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
void Curl_http_auth_cleanup_ntlm_wb(struct connectdata *conn)
|
||||
{
|
||||
ntlm_wb_cleanup(&conn->ntlm);
|
||||
ntlm_wb_cleanup(&conn->proxyntlm);
|
||||
}
|
||||
|
||||
#endif /* !CURL_DISABLE_HTTP && USE_NTLM && NTLM_WB_ENABLED */
|
||||
|
@ -55,7 +55,7 @@ CURLcode Curl_getworkingpath(struct connectdata *conn,
|
||||
}
|
||||
if((working_path_len > 3) && (!memcmp(working_path, "/~/", 3)))
|
||||
/* It is referenced to the home directory, so strip the leading '/~/' */
|
||||
memcpy(real_path, working_path + 3, 4 + working_path_len-3);
|
||||
memcpy(real_path, working_path + 3, working_path_len - 2);
|
||||
else
|
||||
memcpy(real_path, working_path, 1 + working_path_len);
|
||||
}
|
||||
|
@ -199,13 +199,13 @@ static CURLcode rtmp_setup_connection(struct connectdata *conn)
|
||||
RTMP_Free(r);
|
||||
return CURLE_URL_MALFORMAT;
|
||||
}
|
||||
conn->proto.generic = r;
|
||||
conn->proto.rtmp = r;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static CURLcode rtmp_connect(struct connectdata *conn, bool *done)
|
||||
{
|
||||
RTMP *r = conn->proto.generic;
|
||||
RTMP *r = conn->proto.rtmp;
|
||||
SET_RCVTIMEO(tv, 10);
|
||||
|
||||
r->m_sb.sb_socket = (int)conn->sock[FIRSTSOCKET];
|
||||
@ -240,7 +240,7 @@ static CURLcode rtmp_connect(struct connectdata *conn, bool *done)
|
||||
static CURLcode rtmp_do(struct connectdata *conn, bool *done)
|
||||
{
|
||||
struct Curl_easy *data = conn->data;
|
||||
RTMP *r = conn->proto.generic;
|
||||
RTMP *r = conn->proto.rtmp;
|
||||
|
||||
if(!RTMP_ConnectStream(r, 0))
|
||||
return CURLE_FAILED_INIT;
|
||||
@ -268,10 +268,10 @@ static CURLcode rtmp_done(struct connectdata *conn, CURLcode status,
|
||||
static CURLcode rtmp_disconnect(struct connectdata *conn,
|
||||
bool dead_connection)
|
||||
{
|
||||
RTMP *r = conn->proto.generic;
|
||||
RTMP *r = conn->proto.rtmp;
|
||||
(void)dead_connection;
|
||||
if(r) {
|
||||
conn->proto.generic = NULL;
|
||||
conn->proto.rtmp = NULL;
|
||||
RTMP_Close(r);
|
||||
RTMP_Free(r);
|
||||
}
|
||||
@ -281,7 +281,7 @@ static CURLcode rtmp_disconnect(struct connectdata *conn,
|
||||
static ssize_t rtmp_recv(struct connectdata *conn, int sockindex, char *buf,
|
||||
size_t len, CURLcode *err)
|
||||
{
|
||||
RTMP *r = conn->proto.generic;
|
||||
RTMP *r = conn->proto.rtmp;
|
||||
ssize_t nread;
|
||||
|
||||
(void)sockindex; /* unused */
|
||||
@ -302,7 +302,7 @@ static ssize_t rtmp_recv(struct connectdata *conn, int sockindex, char *buf,
|
||||
static ssize_t rtmp_send(struct connectdata *conn, int sockindex,
|
||||
const void *buf, size_t len, CURLcode *err)
|
||||
{
|
||||
RTMP *r = conn->proto.generic;
|
||||
RTMP *r = conn->proto.rtmp;
|
||||
ssize_t num;
|
||||
|
||||
(void)sockindex; /* unused */
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2010, Howard Chu, <hyc@highlandsun.com>
|
||||
* Copyright (C) 2010 - 2019, Howard Chu, <hyc@highlandsun.com>
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 2012 - 2020, 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
|
||||
@ -272,6 +272,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
|
||||
data->set.str[STRING_SERVICE_NAME] :
|
||||
sasl->params->service;
|
||||
#endif
|
||||
const char *oauth_bearer = data->set.str[STRING_BEARER];
|
||||
|
||||
sasl->force_ir = force_ir; /* Latch for future use */
|
||||
sasl->authused = 0; /* No mechanism used yet */
|
||||
@ -341,7 +342,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if((enabledmechs & SASL_MECH_OAUTHBEARER) && conn->oauth_bearer) {
|
||||
if((enabledmechs & SASL_MECH_OAUTHBEARER) && oauth_bearer) {
|
||||
mech = SASL_MECH_STRING_OAUTHBEARER;
|
||||
state1 = SASL_OAUTH2;
|
||||
state2 = SASL_OAUTH2_RESP;
|
||||
@ -351,17 +352,17 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
|
||||
result = Curl_auth_create_oauth_bearer_message(data, conn->user,
|
||||
hostname,
|
||||
port,
|
||||
conn->oauth_bearer,
|
||||
oauth_bearer,
|
||||
&resp, &len);
|
||||
}
|
||||
else if((enabledmechs & SASL_MECH_XOAUTH2) && conn->oauth_bearer) {
|
||||
else if((enabledmechs & SASL_MECH_XOAUTH2) && oauth_bearer) {
|
||||
mech = SASL_MECH_STRING_XOAUTH2;
|
||||
state1 = SASL_OAUTH2;
|
||||
sasl->authused = SASL_MECH_XOAUTH2;
|
||||
|
||||
if(force_ir || data->set.sasl_ir)
|
||||
result = Curl_auth_create_xoauth_bearer_message(data, conn->user,
|
||||
conn->oauth_bearer,
|
||||
oauth_bearer,
|
||||
&resp, &len);
|
||||
}
|
||||
else if(enabledmechs & SASL_MECH_PLAIN) {
|
||||
@ -370,8 +371,9 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
|
||||
sasl->authused = SASL_MECH_PLAIN;
|
||||
|
||||
if(force_ir || data->set.sasl_ir)
|
||||
result = Curl_auth_create_plain_message(data, NULL, conn->user,
|
||||
conn->passwd, &resp, &len);
|
||||
result = Curl_auth_create_plain_message(data, conn->sasl_authzid,
|
||||
conn->user, conn->passwd,
|
||||
&resp, &len);
|
||||
}
|
||||
else if(enabledmechs & SASL_MECH_LOGIN) {
|
||||
mech = SASL_MECH_STRING_LOGIN;
|
||||
@ -430,6 +432,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
|
||||
char *serverdata;
|
||||
#endif
|
||||
size_t len = 0;
|
||||
const char *oauth_bearer = data->set.str[STRING_BEARER];
|
||||
|
||||
*progress = SASL_INPROGRESS;
|
||||
|
||||
@ -453,8 +456,9 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
|
||||
*progress = SASL_DONE;
|
||||
return result;
|
||||
case SASL_PLAIN:
|
||||
result = Curl_auth_create_plain_message(data, NULL, conn->user,
|
||||
conn->passwd, &resp, &len);
|
||||
result = Curl_auth_create_plain_message(data, conn->sasl_authzid,
|
||||
conn->user, conn->passwd,
|
||||
&resp, &len);
|
||||
break;
|
||||
case SASL_LOGIN:
|
||||
result = Curl_auth_create_login_message(data, conn->user, &resp, &len);
|
||||
@ -556,7 +560,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
|
||||
result = Curl_auth_create_oauth_bearer_message(data, conn->user,
|
||||
hostname,
|
||||
port,
|
||||
conn->oauth_bearer,
|
||||
oauth_bearer,
|
||||
&resp, &len);
|
||||
|
||||
/* Failures maybe sent by the server as continuations for OAUTHBEARER */
|
||||
@ -564,7 +568,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
|
||||
}
|
||||
else
|
||||
result = Curl_auth_create_xoauth_bearer_message(data, conn->user,
|
||||
conn->oauth_bearer,
|
||||
oauth_bearer,
|
||||
&resp, &len);
|
||||
break;
|
||||
|
||||
|
@ -26,6 +26,14 @@
|
||||
#define CURL_NO_OLDIES
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Disable Visual Studio warnings:
|
||||
* 4127 "conditional expression is constant"
|
||||
*/
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4127)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Define WIN32 when build target is Win32 API
|
||||
*/
|
||||
@ -96,6 +104,10 @@
|
||||
# include "config-vxworks.h"
|
||||
#endif
|
||||
|
||||
#ifdef __PLAN9__
|
||||
# include "config-plan9.h"
|
||||
#endif
|
||||
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
@ -497,7 +509,6 @@
|
||||
#ifdef WIN32
|
||||
|
||||
# define DIR_CHAR "\\"
|
||||
# define DOT_CHAR "_"
|
||||
|
||||
#else /* WIN32 */
|
||||
|
||||
@ -523,14 +534,6 @@
|
||||
# endif
|
||||
|
||||
# define DIR_CHAR "/"
|
||||
# ifndef DOT_CHAR
|
||||
# define DOT_CHAR "."
|
||||
# endif
|
||||
|
||||
# ifdef MSDOS
|
||||
# undef DOT_CHAR
|
||||
# define DOT_CHAR "_"
|
||||
# endif
|
||||
|
||||
# ifndef fileno /* sunos 4 have this as a macro! */
|
||||
int fileno(FILE *stream);
|
||||
@ -583,6 +586,12 @@
|
||||
* Mutually exclusive CURLRES_* definitions.
|
||||
*/
|
||||
|
||||
#if defined(ENABLE_IPV6) && defined(HAVE_GETADDRINFO)
|
||||
# define CURLRES_IPV6
|
||||
#else
|
||||
# define CURLRES_IPV4
|
||||
#endif
|
||||
|
||||
#ifdef USE_ARES
|
||||
# define CURLRES_ASYNCH
|
||||
# define CURLRES_ARES
|
||||
@ -597,12 +606,6 @@
|
||||
# define CURLRES_SYNCH
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_IPV6
|
||||
# define CURLRES_IPV6
|
||||
#else
|
||||
# define CURLRES_IPV4
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
@ -662,9 +665,10 @@ int netware_init(void);
|
||||
#define LIBIDN_REQUIRED_VERSION "0.4.1"
|
||||
|
||||
#if defined(USE_GNUTLS) || defined(USE_OPENSSL) || defined(USE_NSS) || \
|
||||
defined(USE_POLARSSL) || defined(USE_MBEDTLS) || \
|
||||
defined(USE_CYASSL) || defined(USE_SCHANNEL) || \
|
||||
defined(USE_SECTRANSP) || defined(USE_GSKIT) || defined(USE_MESALINK)
|
||||
defined(USE_MBEDTLS) || \
|
||||
defined(USE_WOLFSSL) || defined(USE_SCHANNEL) || \
|
||||
defined(USE_SECTRANSP) || defined(USE_GSKIT) || defined(USE_MESALINK) || \
|
||||
defined(USE_BEARSSL)
|
||||
#define USE_SSL /* SSL support has been enabled */
|
||||
#endif
|
||||
|
||||
@ -733,7 +737,7 @@ int netware_init(void);
|
||||
*/
|
||||
|
||||
#ifndef Curl_nop_stmt
|
||||
# define Curl_nop_stmt do { } WHILE_FALSE
|
||||
# define Curl_nop_stmt do { } while(0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -842,4 +846,8 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf,
|
||||
#define UNITTEST static
|
||||
#endif
|
||||
|
||||
#if defined(USE_NGTCP2) || defined(USE_QUICHE)
|
||||
#define ENABLE_QUIC
|
||||
#endif
|
||||
|
||||
#endif /* HEADER_CURL_SETUP_H */
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2019, 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
|
||||
@ -329,27 +329,6 @@ struct timeval {
|
||||
|
||||
#include "curl_ctype.h"
|
||||
|
||||
/*
|
||||
* Macro WHILE_FALSE may be used to build single-iteration do-while loops,
|
||||
* avoiding compiler warnings. Mostly intended for other macro definitions.
|
||||
*/
|
||||
|
||||
#define WHILE_FALSE while(0)
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__POCC__)
|
||||
# undef WHILE_FALSE
|
||||
# if (_MSC_VER < 1500)
|
||||
# define WHILE_FALSE while(1, 0)
|
||||
# else
|
||||
# define WHILE_FALSE \
|
||||
__pragma(warning(push)) \
|
||||
__pragma(warning(disable:4127)) \
|
||||
while(0) \
|
||||
__pragma(warning(pop))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Typedef to 'int' if sig_atomic_t is not an available 'typedefed' type.
|
||||
*/
|
||||
@ -387,7 +366,7 @@ typedef int sig_atomic_t;
|
||||
#ifdef DEBUGBUILD
|
||||
#define DEBUGF(x) x
|
||||
#else
|
||||
#define DEBUGF(x) do { } WHILE_FALSE
|
||||
#define DEBUGF(x) do { } while(0)
|
||||
#endif
|
||||
|
||||
|
||||
@ -395,10 +374,11 @@ typedef int sig_atomic_t;
|
||||
* Macro used to include assertion code only in debug builds.
|
||||
*/
|
||||
|
||||
#undef DEBUGASSERT
|
||||
#if defined(DEBUGBUILD) && defined(HAVE_ASSERT_H)
|
||||
#define DEBUGASSERT(x) assert(x)
|
||||
#else
|
||||
#define DEBUGASSERT(x) do { } WHILE_FALSE
|
||||
#define DEBUGASSERT(x) do { } while(0)
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -7,7 +7,8 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2010, Florin Petriuc, <petriuc.florin@gmail.com>
|
||||
* Copyright (C) 2017, Florin Petriuc, <petriuc.florin@gmail.com>
|
||||
* Copyright (C) 2018 - 2020, 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
|
||||
@ -24,8 +25,10 @@
|
||||
|
||||
#ifndef CURL_DISABLE_CRYPTO_AUTH
|
||||
|
||||
void Curl_sha256it(unsigned char *outbuffer,
|
||||
const unsigned char *input);
|
||||
#define SHA256_DIGEST_LENGTH 32
|
||||
|
||||
void Curl_sha256it(unsigned char *outbuffer, const unsigned char *input,
|
||||
const size_t len);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2019, 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
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2019, 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
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2019, 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
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2019, 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
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2019, 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
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 2018 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 2018 - 2020, 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
|
||||
@ -74,17 +74,50 @@ static const char *doh_strerror(DOHcode code)
|
||||
#define UNITTEST static
|
||||
#endif
|
||||
|
||||
/* @unittest 1655
|
||||
*/
|
||||
UNITTEST DOHcode doh_encode(const char *host,
|
||||
DNStype dnstype,
|
||||
unsigned char *dnsp, /* buffer */
|
||||
size_t len, /* buffer size */
|
||||
size_t *olen) /* output length */
|
||||
{
|
||||
size_t hostlen = strlen(host);
|
||||
const size_t hostlen = strlen(host);
|
||||
unsigned char *orig = dnsp;
|
||||
const char *hostp = host;
|
||||
|
||||
if(len < (12 + hostlen + 4))
|
||||
/* The expected output length is 16 bytes more than the length of
|
||||
* the QNAME-encoding of the host name.
|
||||
*
|
||||
* A valid DNS name may not contain a zero-length label, except at
|
||||
* the end. For this reason, a name beginning with a dot, or
|
||||
* containing a sequence of two or more consecutive dots, is invalid
|
||||
* and cannot be encoded as a QNAME.
|
||||
*
|
||||
* If the host name ends with a trailing dot, the corresponding
|
||||
* QNAME-encoding is one byte longer than the host name. If (as is
|
||||
* also valid) the hostname is shortened by the omission of the
|
||||
* trailing dot, then its QNAME-encoding will be two bytes longer
|
||||
* than the host name.
|
||||
*
|
||||
* Each [ label, dot ] pair is encoded as [ length, label ],
|
||||
* preserving overall length. A final [ label ] without a dot is
|
||||
* also encoded as [ length, label ], increasing overall length
|
||||
* by one. The encoding is completed by appending a zero byte,
|
||||
* representing the zero-length root label, again increasing
|
||||
* the overall length by one.
|
||||
*/
|
||||
|
||||
size_t expected_len;
|
||||
DEBUGASSERT(hostlen);
|
||||
expected_len = 12 + 1 + hostlen + 4;
|
||||
if(host[hostlen-1]!='.')
|
||||
expected_len++;
|
||||
|
||||
if(expected_len > (256 + 16)) /* RFCs 1034, 1035 */
|
||||
return DOH_DNS_NAME_TOO_LONG;
|
||||
|
||||
if(len < expected_len)
|
||||
return DOH_TOO_SMALL_BUFFER;
|
||||
|
||||
*dnsp++ = 0; /* 16 bit id */
|
||||
@ -100,38 +133,43 @@ UNITTEST DOHcode doh_encode(const char *host,
|
||||
*dnsp++ = '\0';
|
||||
*dnsp++ = '\0'; /* ARCOUNT */
|
||||
|
||||
/* store a QNAME */
|
||||
do {
|
||||
char *dot = strchr(hostp, '.');
|
||||
/* encode each label and store it in the QNAME */
|
||||
while(*hostp) {
|
||||
size_t labellen;
|
||||
bool found = false;
|
||||
if(dot) {
|
||||
found = true;
|
||||
char *dot = strchr(hostp, '.');
|
||||
if(dot)
|
||||
labellen = dot - hostp;
|
||||
}
|
||||
else
|
||||
labellen = strlen(hostp);
|
||||
if(labellen > 63) {
|
||||
/* too long label, error out */
|
||||
if((labellen > 63) || (!labellen)) {
|
||||
/* label is too long or too short, error out */
|
||||
*olen = 0;
|
||||
return DOH_DNS_BAD_LABEL;
|
||||
}
|
||||
/* label is non-empty, process it */
|
||||
*dnsp++ = (unsigned char)labellen;
|
||||
memcpy(dnsp, hostp, labellen);
|
||||
dnsp += labellen;
|
||||
hostp += labellen + 1;
|
||||
if(!found) {
|
||||
*dnsp++ = 0; /* terminating zero */
|
||||
break;
|
||||
}
|
||||
} while(1);
|
||||
hostp += labellen;
|
||||
/* advance past dot, but only if there is one */
|
||||
if(dot)
|
||||
hostp++;
|
||||
} /* next label */
|
||||
|
||||
*dnsp++ = 0; /* append zero-length label for root */
|
||||
|
||||
/* There are assigned TYPE codes beyond 255: use range [1..65535] */
|
||||
*dnsp++ = (unsigned char)(255 & (dnstype>>8)); /* upper 8 bit TYPE */
|
||||
*dnsp++ = (unsigned char)(255 & dnstype); /* lower 8 bit TYPE */
|
||||
|
||||
*dnsp++ = '\0'; /* upper 8 bit TYPE */
|
||||
*dnsp++ = (unsigned char)dnstype;
|
||||
*dnsp++ = '\0'; /* upper 8 bit CLASS */
|
||||
*dnsp++ = DNS_CLASS_IN; /* IN - "the Internet" */
|
||||
|
||||
*olen = dnsp - orig;
|
||||
|
||||
/* verify that our estimation of length is valid, since
|
||||
* this has led to buffer overflows in this function */
|
||||
DEBUGASSERT(*olen == expected_len);
|
||||
return DOH_OK;
|
||||
}
|
||||
|
||||
@ -180,7 +218,7 @@ do { \
|
||||
result = curl_easy_setopt(doh, x, y); \
|
||||
if(result) \
|
||||
goto error; \
|
||||
} WHILE_FALSE
|
||||
} while(0)
|
||||
|
||||
static CURLcode dohprobe(struct Curl_easy *data,
|
||||
struct dnsprobe *p, DNStype dnstype,
|
||||
@ -225,7 +263,10 @@ static CURLcode dohprobe(struct Curl_easy *data,
|
||||
}
|
||||
|
||||
timeout_ms = Curl_timeleft(data, NULL, TRUE);
|
||||
|
||||
if(timeout_ms <= 0) {
|
||||
result = CURLE_OPERATION_TIMEDOUT;
|
||||
goto error;
|
||||
}
|
||||
/* Curl_open() is the internal version of curl_easy_init() */
|
||||
result = Curl_open(&doh);
|
||||
if(!result) {
|
||||
@ -246,6 +287,9 @@ static CURLcode dohprobe(struct Curl_easy *data,
|
||||
#ifndef CURLDEBUG
|
||||
/* enforce HTTPS if not debug */
|
||||
ERROR_CHECK_SETOPT(CURLOPT_PROTOCOLS, CURLPROTO_HTTPS);
|
||||
#else
|
||||
/* in debug mode, also allow http */
|
||||
ERROR_CHECK_SETOPT(CURLOPT_PROTOCOLS, CURLPROTO_HTTP|CURLPROTO_HTTPS);
|
||||
#endif
|
||||
ERROR_CHECK_SETOPT(CURLOPT_TIMEOUT_MS, (long)timeout_ms);
|
||||
if(data->set.verbose)
|
||||
@ -259,38 +303,42 @@ static CURLcode dohprobe(struct Curl_easy *data,
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SSL_FALSESTART, 1L);
|
||||
if(data->set.ssl.primary.verifyhost)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYHOST, 2L);
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
if(data->set.proxy_ssl.primary.verifyhost)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_VERIFYHOST, 2L);
|
||||
if(data->set.ssl.primary.verifypeer)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYPEER, 1L);
|
||||
if(data->set.proxy_ssl.primary.verifypeer)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_VERIFYPEER, 1L);
|
||||
if(data->set.str[STRING_SSL_CAFILE_PROXY]) {
|
||||
ERROR_CHECK_SETOPT(CURLOPT_PROXY_CAINFO,
|
||||
data->set.str[STRING_SSL_CAFILE_PROXY]);
|
||||
}
|
||||
if(data->set.str[STRING_SSL_CRLFILE_PROXY]) {
|
||||
ERROR_CHECK_SETOPT(CURLOPT_PROXY_CRLFILE,
|
||||
data->set.str[STRING_SSL_CRLFILE_PROXY]);
|
||||
}
|
||||
if(data->set.proxy_ssl.no_revoke)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE);
|
||||
if(data->set.str[STRING_SSL_CAPATH_PROXY]) {
|
||||
ERROR_CHECK_SETOPT(CURLOPT_PROXY_CAPATH,
|
||||
data->set.str[STRING_SSL_CAPATH_PROXY]);
|
||||
}
|
||||
#endif
|
||||
if(data->set.ssl.primary.verifypeer)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYPEER, 1L);
|
||||
if(data->set.ssl.primary.verifystatus)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYSTATUS, 1L);
|
||||
if(data->set.str[STRING_SSL_CAFILE_ORIG]) {
|
||||
ERROR_CHECK_SETOPT(CURLOPT_CAINFO,
|
||||
data->set.str[STRING_SSL_CAFILE_ORIG]);
|
||||
}
|
||||
if(data->set.str[STRING_SSL_CAFILE_PROXY]) {
|
||||
ERROR_CHECK_SETOPT(CURLOPT_PROXY_CAINFO,
|
||||
data->set.str[STRING_SSL_CAFILE_PROXY]);
|
||||
}
|
||||
if(data->set.str[STRING_SSL_CAPATH_ORIG]) {
|
||||
ERROR_CHECK_SETOPT(CURLOPT_CAPATH,
|
||||
data->set.str[STRING_SSL_CAPATH_ORIG]);
|
||||
}
|
||||
if(data->set.str[STRING_SSL_CAPATH_PROXY]) {
|
||||
ERROR_CHECK_SETOPT(CURLOPT_PROXY_CAPATH,
|
||||
data->set.str[STRING_SSL_CAPATH_PROXY]);
|
||||
}
|
||||
if(data->set.str[STRING_SSL_CRLFILE_ORIG]) {
|
||||
ERROR_CHECK_SETOPT(CURLOPT_CRLFILE,
|
||||
data->set.str[STRING_SSL_CRLFILE_ORIG]);
|
||||
}
|
||||
if(data->set.str[STRING_SSL_CRLFILE_PROXY]) {
|
||||
ERROR_CHECK_SETOPT(CURLOPT_PROXY_CRLFILE,
|
||||
data->set.str[STRING_SSL_CRLFILE_PROXY]);
|
||||
}
|
||||
if(data->set.ssl.certinfo)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_CERTINFO, 1L);
|
||||
if(data->set.str[STRING_SSL_RANDOM_FILE]) {
|
||||
@ -303,8 +351,6 @@ static CURLcode dohprobe(struct Curl_easy *data,
|
||||
}
|
||||
if(data->set.ssl.no_revoke)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE);
|
||||
if(data->set.proxy_ssl.no_revoke)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE);
|
||||
if(data->set.ssl.fsslctx)
|
||||
ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_FUNCTION, data->set.ssl.fsslctx);
|
||||
if(data->set.ssl.fsslctxp)
|
||||
@ -325,7 +371,7 @@ static CURLcode dohprobe(struct Curl_easy *data,
|
||||
|
||||
error:
|
||||
free(nurl);
|
||||
Curl_close(doh);
|
||||
Curl_close(&doh);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -341,6 +387,7 @@ Curl_addrinfo *Curl_doh(struct connectdata *conn,
|
||||
{
|
||||
struct Curl_easy *data = conn->data;
|
||||
CURLcode result = CURLE_OK;
|
||||
int slot;
|
||||
*waitp = TRUE; /* this never returns synchronously */
|
||||
(void)conn;
|
||||
(void)hostname;
|
||||
@ -359,8 +406,8 @@ Curl_addrinfo *Curl_doh(struct connectdata *conn,
|
||||
|
||||
if(conn->ip_version != CURL_IPRESOLVE_V6) {
|
||||
/* create IPv4 DOH request */
|
||||
result = dohprobe(data, &data->req.doh.probe[0], DNS_TYPE_A,
|
||||
hostname, data->set.str[STRING_DOH],
|
||||
result = dohprobe(data, &data->req.doh.probe[DOH_PROBE_SLOT_IPADDR_V4],
|
||||
DNS_TYPE_A, hostname, data->set.str[STRING_DOH],
|
||||
data->multi, data->req.doh.headers);
|
||||
if(result)
|
||||
goto error;
|
||||
@ -369,8 +416,8 @@ Curl_addrinfo *Curl_doh(struct connectdata *conn,
|
||||
|
||||
if(conn->ip_version != CURL_IPRESOLVE_V4) {
|
||||
/* create IPv6 DOH request */
|
||||
result = dohprobe(data, &data->req.doh.probe[1], DNS_TYPE_AAAA,
|
||||
hostname, data->set.str[STRING_DOH],
|
||||
result = dohprobe(data, &data->req.doh.probe[DOH_PROBE_SLOT_IPADDR_V6],
|
||||
DNS_TYPE_AAAA, hostname, data->set.str[STRING_DOH],
|
||||
data->multi, data->req.doh.headers);
|
||||
if(result)
|
||||
goto error;
|
||||
@ -381,10 +428,9 @@ Curl_addrinfo *Curl_doh(struct connectdata *conn,
|
||||
error:
|
||||
curl_slist_free_all(data->req.doh.headers);
|
||||
data->req.doh.headers = NULL;
|
||||
curl_easy_cleanup(data->req.doh.probe[0].easy);
|
||||
data->req.doh.probe[0].easy = NULL;
|
||||
curl_easy_cleanup(data->req.doh.probe[1].easy);
|
||||
data->req.doh.probe[1].easy = NULL;
|
||||
for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) {
|
||||
Curl_close(&data->req.doh.probe[slot].easy);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -419,8 +465,14 @@ static unsigned short get16bit(unsigned char *doh, int index)
|
||||
|
||||
static unsigned int get32bit(unsigned char *doh, int index)
|
||||
{
|
||||
return (doh[index] << 24) | (doh[index + 1] << 16) |
|
||||
(doh[index + 2] << 8) | doh[index + 3];
|
||||
/* make clang and gcc optimize this to bswap by incrementing
|
||||
the pointer first. */
|
||||
doh += index;
|
||||
|
||||
/* avoid undefined behaviour by casting to unsigned before shifting
|
||||
24 bits, possibly into the sign bit. codegen is same, but
|
||||
ub sanitizer won't be upset */
|
||||
return ( (unsigned)doh[0] << 24) | (doh[1] << 16) |(doh[2] << 8) | doh[3];
|
||||
}
|
||||
|
||||
static DOHcode store_a(unsigned char *doh, int index, struct dohentry *d)
|
||||
@ -496,7 +548,7 @@ static DOHcode store_cname(unsigned char *doh,
|
||||
if((index + 1) >= dohlen)
|
||||
return DOH_DNS_OUT_OF_RANGE;
|
||||
|
||||
/* move to the the new index */
|
||||
/* move to the new index */
|
||||
newpos = (length & 0x3f) << 8 | doh[index + 1];
|
||||
index = newpos;
|
||||
continue;
|
||||
@ -561,6 +613,9 @@ static DOHcode rdata(unsigned char *doh,
|
||||
if(rc)
|
||||
return rc;
|
||||
break;
|
||||
case DNS_TYPE_DNAME:
|
||||
/* explicit for clarity; just skip; rely on synthesized CNAME */
|
||||
break;
|
||||
default:
|
||||
/* unsupported type, just skip it */
|
||||
break;
|
||||
@ -622,8 +677,10 @@ UNITTEST DOHcode doh_decode(unsigned char *doh,
|
||||
return DOH_DNS_OUT_OF_RANGE;
|
||||
|
||||
type = get16bit(doh, index);
|
||||
if((type != DNS_TYPE_CNAME) && (type != dnstype))
|
||||
/* Not the same type as was asked for nor CNAME */
|
||||
if((type != DNS_TYPE_CNAME) /* may be synthesized from DNAME */
|
||||
&& (type != DNS_TYPE_DNAME) /* if present, accept and ignore */
|
||||
&& (type != dnstype))
|
||||
/* Not the same type as was asked for nor CNAME nor DNAME */
|
||||
return DOH_DNS_UNEXPECTED_TYPE;
|
||||
index += 2;
|
||||
|
||||
@ -884,47 +941,43 @@ UNITTEST void de_cleanup(struct dohentry *d)
|
||||
CURLcode Curl_doh_is_resolved(struct connectdata *conn,
|
||||
struct Curl_dns_entry **dnsp)
|
||||
{
|
||||
CURLcode result;
|
||||
struct Curl_easy *data = conn->data;
|
||||
*dnsp = NULL; /* defaults to no response */
|
||||
|
||||
if(!data->req.doh.probe[0].easy && !data->req.doh.probe[1].easy) {
|
||||
if(!data->req.doh.probe[DOH_PROBE_SLOT_IPADDR_V4].easy &&
|
||||
!data->req.doh.probe[DOH_PROBE_SLOT_IPADDR_V6].easy) {
|
||||
failf(data, "Could not DOH-resolve: %s", conn->async.hostname);
|
||||
return conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
|
||||
CURLE_COULDNT_RESOLVE_HOST;
|
||||
}
|
||||
else if(!data->req.doh.pending) {
|
||||
DOHcode rc;
|
||||
DOHcode rc2;
|
||||
DOHcode rc[DOH_PROBE_SLOTS];
|
||||
struct dohentry de;
|
||||
int slot;
|
||||
/* remove DOH handles from multi handle and close them */
|
||||
curl_multi_remove_handle(data->multi, data->req.doh.probe[0].easy);
|
||||
Curl_close(data->req.doh.probe[0].easy);
|
||||
curl_multi_remove_handle(data->multi, data->req.doh.probe[1].easy);
|
||||
Curl_close(data->req.doh.probe[1].easy);
|
||||
|
||||
for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) {
|
||||
curl_multi_remove_handle(data->multi, data->req.doh.probe[slot].easy);
|
||||
Curl_close(&data->req.doh.probe[slot].easy);
|
||||
}
|
||||
/* parse the responses, create the struct and return it! */
|
||||
init_dohentry(&de);
|
||||
rc = doh_decode(data->req.doh.probe[0].serverdoh.memory,
|
||||
data->req.doh.probe[0].serverdoh.size,
|
||||
data->req.doh.probe[0].dnstype,
|
||||
&de);
|
||||
free(data->req.doh.probe[0].serverdoh.memory);
|
||||
if(rc) {
|
||||
infof(data, "DOH: %s type %s for %s\n", doh_strerror(rc),
|
||||
type2name(data->req.doh.probe[0].dnstype),
|
||||
data->req.doh.host);
|
||||
}
|
||||
rc2 = doh_decode(data->req.doh.probe[1].serverdoh.memory,
|
||||
data->req.doh.probe[1].serverdoh.size,
|
||||
data->req.doh.probe[1].dnstype,
|
||||
&de);
|
||||
free(data->req.doh.probe[1].serverdoh.memory);
|
||||
if(rc2) {
|
||||
infof(data, "DOH: %s type %s for %s\n", doh_strerror(rc2),
|
||||
type2name(data->req.doh.probe[1].dnstype),
|
||||
data->req.doh.host);
|
||||
}
|
||||
if(!rc || !rc2) {
|
||||
for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) {
|
||||
rc[slot] = doh_decode(data->req.doh.probe[slot].serverdoh.memory,
|
||||
data->req.doh.probe[slot].serverdoh.size,
|
||||
data->req.doh.probe[slot].dnstype,
|
||||
&de);
|
||||
Curl_safefree(data->req.doh.probe[slot].serverdoh.memory);
|
||||
if(rc[slot]) {
|
||||
infof(data, "DOH: %s type %s for %s\n", doh_strerror(rc[slot]),
|
||||
type2name(data->req.doh.probe[slot].dnstype),
|
||||
data->req.doh.host);
|
||||
}
|
||||
} /* next slot */
|
||||
|
||||
result = CURLE_COULDNT_RESOLVE_HOST; /* until we know better */
|
||||
if(!rc[DOH_PROBE_SLOT_IPADDR_V4] || !rc[DOH_PROBE_SLOT_IPADDR_V6]) {
|
||||
/* we have an address, of one kind or other */
|
||||
struct Curl_dns_entry *dns;
|
||||
struct Curl_addrinfo *ai;
|
||||
|
||||
@ -946,21 +999,26 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
|
||||
if(data->share)
|
||||
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
|
||||
|
||||
de_cleanup(&de);
|
||||
if(!dns)
|
||||
if(!dns) {
|
||||
/* returned failure, bail out nicely */
|
||||
Curl_freeaddrinfo(ai);
|
||||
}
|
||||
else {
|
||||
conn->async.dns = dns;
|
||||
*dnsp = dns;
|
||||
return CURLE_OK;
|
||||
result = CURLE_OK; /* address resolution OK */
|
||||
}
|
||||
}
|
||||
} /* address processing done */
|
||||
|
||||
/* Now process any build-specific attributes retrieved from DNS */
|
||||
|
||||
/* All done */
|
||||
de_cleanup(&de);
|
||||
return result;
|
||||
|
||||
return CURLE_COULDNT_RESOLVE_HOST;
|
||||
}
|
||||
} /* !data->req.doh.pending */
|
||||
|
||||
/* else wait for pending DOH transactions to complete */
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
|
@ -40,8 +40,7 @@ Curl_addrinfo *Curl_doh(struct connectdata *conn,
|
||||
CURLcode Curl_doh_is_resolved(struct connectdata *conn,
|
||||
struct Curl_dns_entry **dns);
|
||||
|
||||
int Curl_doh_getsock(struct connectdata *conn, curl_socket_t *socks,
|
||||
int numsocks);
|
||||
int Curl_doh_getsock(struct connectdata *conn, curl_socket_t *socks);
|
||||
|
||||
typedef enum {
|
||||
DOH_OK,
|
||||
@ -56,14 +55,16 @@ typedef enum {
|
||||
DOH_DNS_UNEXPECTED_TYPE, /* 9 */
|
||||
DOH_DNS_UNEXPECTED_CLASS, /* 10 */
|
||||
DOH_NO_CONTENT, /* 11 */
|
||||
DOH_DNS_BAD_ID /* 12 */
|
||||
DOH_DNS_BAD_ID, /* 12 */
|
||||
DOH_DNS_NAME_TOO_LONG /* 13 */
|
||||
} DOHcode;
|
||||
|
||||
typedef enum {
|
||||
DNS_TYPE_A = 1,
|
||||
DNS_TYPE_NS = 2,
|
||||
DNS_TYPE_CNAME = 5,
|
||||
DNS_TYPE_AAAA = 28
|
||||
DNS_TYPE_AAAA = 28,
|
||||
DNS_TYPE_DNAME = 39 /* RFC6672 */
|
||||
} DNStype;
|
||||
|
||||
#define DOH_MAX_ADDR 24
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2019, 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
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2019, 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
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2020, 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
|
||||
@ -72,10 +72,11 @@
|
||||
#include "warnless.h"
|
||||
#include "multiif.h"
|
||||
#include "sigpipe.h"
|
||||
#include "ssh.h"
|
||||
#include "vssh/ssh.h"
|
||||
#include "setopt.h"
|
||||
#include "http_digest.h"
|
||||
#include "system_win32.h"
|
||||
#include "http2.h"
|
||||
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
@ -157,20 +158,20 @@ static CURLcode global_init(long flags, bool memoryfuncs)
|
||||
|
||||
if(!Curl_ssl_init()) {
|
||||
DEBUGF(fprintf(stderr, "Error: Curl_ssl_init failed\n"));
|
||||
return CURLE_FAILED_INIT;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
if(Curl_win32_init(flags)) {
|
||||
DEBUGF(fprintf(stderr, "Error: win32_init failed\n"));
|
||||
return CURLE_FAILED_INIT;
|
||||
goto fail;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __AMIGA__
|
||||
if(!Curl_amiga_init()) {
|
||||
DEBUGF(fprintf(stderr, "Error: Curl_amiga_init failed\n"));
|
||||
return CURLE_FAILED_INIT;
|
||||
goto fail;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -182,33 +183,31 @@ static CURLcode global_init(long flags, bool memoryfuncs)
|
||||
|
||||
if(Curl_resolver_global_init()) {
|
||||
DEBUGF(fprintf(stderr, "Error: resolver_global_init failed\n"));
|
||||
return CURLE_FAILED_INIT;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
(void)Curl_ipv6works();
|
||||
|
||||
#if defined(USE_LIBSSH2) && defined(HAVE_LIBSSH2_INIT)
|
||||
if(libssh2_init(0)) {
|
||||
DEBUGF(fprintf(stderr, "Error: libssh2_init failed\n"));
|
||||
return CURLE_FAILED_INIT;
|
||||
#if defined(USE_SSH)
|
||||
if(Curl_ssh_init()) {
|
||||
goto fail;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(USE_LIBSSH)
|
||||
if(ssh_init()) {
|
||||
DEBUGF(fprintf(stderr, "Error: libssh_init failed\n"));
|
||||
#ifdef USE_WOLFSSH
|
||||
if(WS_SUCCESS != wolfSSH_Init()) {
|
||||
DEBUGF(fprintf(stderr, "Error: wolfSSH_Init failed\n"));
|
||||
return CURLE_FAILED_INIT;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(flags & CURL_GLOBAL_ACK_EINTR)
|
||||
Curl_ack_eintr = 1;
|
||||
|
||||
init_flags = flags;
|
||||
|
||||
Curl_version_init();
|
||||
|
||||
return CURLE_OK;
|
||||
|
||||
fail:
|
||||
initialized--; /* undo the increase */
|
||||
return CURLE_FAILED_INIT;
|
||||
}
|
||||
|
||||
|
||||
@ -274,12 +273,10 @@ void curl_global_cleanup(void)
|
||||
|
||||
Curl_amiga_cleanup();
|
||||
|
||||
#if defined(USE_LIBSSH2) && defined(HAVE_LIBSSH2_EXIT)
|
||||
(void)libssh2_exit();
|
||||
#endif
|
||||
Curl_ssh_cleanup();
|
||||
|
||||
#if defined(USE_LIBSSH)
|
||||
(void)ssh_finalize();
|
||||
#ifdef USE_WOLFSSH
|
||||
(void)wolfSSH_Cleanup();
|
||||
#endif
|
||||
|
||||
init_flags = 0;
|
||||
@ -602,27 +599,11 @@ static CURLcode easy_transfer(struct Curl_multi *multi)
|
||||
|
||||
while(!done && !mcode) {
|
||||
int still_running = 0;
|
||||
bool gotsocket = FALSE;
|
||||
|
||||
mcode = Curl_multi_wait(multi, NULL, 0, 1000, NULL, &gotsocket);
|
||||
|
||||
if(!mcode) {
|
||||
if(!gotsocket) {
|
||||
long sleep_ms;
|
||||
|
||||
/* If it returns without any filedescriptor instantly, we need to
|
||||
avoid busy-looping during periods where it has nothing particular
|
||||
to wait for */
|
||||
curl_multi_timeout(multi, &sleep_ms);
|
||||
if(sleep_ms) {
|
||||
if(sleep_ms > 1000)
|
||||
sleep_ms = 1000;
|
||||
Curl_wait_ms((int)sleep_ms);
|
||||
}
|
||||
}
|
||||
mcode = curl_multi_poll(multi, NULL, 0, 1000, NULL);
|
||||
|
||||
if(!mcode)
|
||||
mcode = curl_multi_perform(multi, &still_running);
|
||||
}
|
||||
|
||||
/* only read 'still_running' if curl_multi_perform() return OK */
|
||||
if(!mcode && !still_running) {
|
||||
@ -710,10 +691,6 @@ static CURLcode easy_perform(struct Curl_easy *data, bool events)
|
||||
|
||||
sigpipe_ignore(data, &pipe_st);
|
||||
|
||||
/* assign this after curl_multi_add_handle() since that function checks for
|
||||
it and rejects this handle otherwise */
|
||||
data->multi = multi;
|
||||
|
||||
/* run the transfer */
|
||||
result = events ? easy_events(multi) : easy_transfer(multi);
|
||||
|
||||
@ -761,7 +738,7 @@ void curl_easy_cleanup(struct Curl_easy *data)
|
||||
return;
|
||||
|
||||
sigpipe_ignore(data, &pipe_st);
|
||||
Curl_close(data);
|
||||
Curl_close(&data);
|
||||
sigpipe_restore(&pipe_st);
|
||||
}
|
||||
|
||||
@ -942,6 +919,8 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
|
||||
*/
|
||||
void curl_easy_reset(struct Curl_easy *data)
|
||||
{
|
||||
long old_buffer_size = data->set.buffer_size;
|
||||
|
||||
Curl_free_request_state(data);
|
||||
|
||||
/* zero out UserDefined data: */
|
||||
@ -965,6 +944,18 @@ void curl_easy_reset(struct Curl_easy *data)
|
||||
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
|
||||
Curl_http_auth_cleanup_digest(data);
|
||||
#endif
|
||||
|
||||
/* resize receive buffer */
|
||||
if(old_buffer_size != data->set.buffer_size) {
|
||||
char *newbuff = realloc(data->state.buffer, data->set.buffer_size + 1);
|
||||
if(!newbuff) {
|
||||
DEBUGF(fprintf(stderr, "Error: realloc of buffer failed\n"));
|
||||
/* nothing we can do here except use the old size */
|
||||
data->set.buffer_size = old_buffer_size;
|
||||
}
|
||||
else
|
||||
data->state.buffer = newbuff;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -995,55 +986,63 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
|
||||
/* put it back in the keepon */
|
||||
k->keepon = newstate;
|
||||
|
||||
if(!(newstate & KEEP_RECV_PAUSE) && data->state.tempcount) {
|
||||
/* there are buffers for sending that can be delivered as the receive
|
||||
pausing is lifted! */
|
||||
unsigned int i;
|
||||
unsigned int count = data->state.tempcount;
|
||||
struct tempbuf writebuf[3]; /* there can only be three */
|
||||
struct connectdata *conn = data->conn;
|
||||
struct Curl_easy *saved_data = NULL;
|
||||
if(!(newstate & KEEP_RECV_PAUSE)) {
|
||||
Curl_http2_stream_pause(data, FALSE);
|
||||
|
||||
/* copy the structs to allow for immediate re-pausing */
|
||||
for(i = 0; i < data->state.tempcount; i++) {
|
||||
writebuf[i] = data->state.tempwrite[i];
|
||||
data->state.tempwrite[i].buf = NULL;
|
||||
if(data->state.tempcount) {
|
||||
/* there are buffers for sending that can be delivered as the receive
|
||||
pausing is lifted! */
|
||||
unsigned int i;
|
||||
unsigned int count = data->state.tempcount;
|
||||
struct tempbuf writebuf[3]; /* there can only be three */
|
||||
struct connectdata *conn = data->conn;
|
||||
struct Curl_easy *saved_data = NULL;
|
||||
|
||||
/* copy the structs to allow for immediate re-pausing */
|
||||
for(i = 0; i < data->state.tempcount; i++) {
|
||||
writebuf[i] = data->state.tempwrite[i];
|
||||
data->state.tempwrite[i].buf = NULL;
|
||||
}
|
||||
data->state.tempcount = 0;
|
||||
|
||||
/* set the connection's current owner */
|
||||
if(conn->data != data) {
|
||||
saved_data = conn->data;
|
||||
conn->data = data;
|
||||
}
|
||||
|
||||
for(i = 0; i < count; i++) {
|
||||
/* even if one function returns error, this loops through and frees
|
||||
all buffers */
|
||||
if(!result)
|
||||
result = Curl_client_write(conn, writebuf[i].type, writebuf[i].buf,
|
||||
writebuf[i].len);
|
||||
free(writebuf[i].buf);
|
||||
}
|
||||
|
||||
/* recover previous owner of the connection */
|
||||
if(saved_data)
|
||||
conn->data = saved_data;
|
||||
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
data->state.tempcount = 0;
|
||||
|
||||
/* set the connection's current owner */
|
||||
if(conn->data != data) {
|
||||
saved_data = conn->data;
|
||||
conn->data = data;
|
||||
}
|
||||
|
||||
for(i = 0; i < count; i++) {
|
||||
/* even if one function returns error, this loops through and frees all
|
||||
buffers */
|
||||
if(!result)
|
||||
result = Curl_client_write(conn, writebuf[i].type, writebuf[i].buf,
|
||||
writebuf[i].len);
|
||||
free(writebuf[i].buf);
|
||||
}
|
||||
|
||||
/* recover previous owner of the connection */
|
||||
if(saved_data)
|
||||
conn->data = saved_data;
|
||||
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* if there's no error and we're not pausing both directions, we want
|
||||
to have this handle checked soon */
|
||||
if(!result &&
|
||||
((newstate&(KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) !=
|
||||
(KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) )
|
||||
if((newstate & (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) !=
|
||||
(KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) {
|
||||
data->state.drain++;
|
||||
Curl_expire(data, 0, EXPIRE_RUN_NOW); /* get this handle going again */
|
||||
if(data->multi)
|
||||
Curl_update_timer(data->multi);
|
||||
}
|
||||
|
||||
/* This transfer may have been moved in or out of the bundle, update
|
||||
the corresponding socket callback, if used */
|
||||
Curl_updatesocket(data);
|
||||
if(!data->state.done)
|
||||
/* This transfer may have been moved in or out of the bundle, update the
|
||||
corresponding socket callback, if used */
|
||||
Curl_updatesocket(data);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -1137,6 +1136,35 @@ CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wrapper to call functions in Curl_conncache_foreach()
|
||||
*
|
||||
* Returns always 0.
|
||||
*/
|
||||
static int conn_upkeep(struct connectdata *conn,
|
||||
void *param)
|
||||
{
|
||||
/* Param is unused. */
|
||||
(void)param;
|
||||
|
||||
if(conn->handler->connection_check) {
|
||||
/* Do a protocol-specific keepalive check on the connection. */
|
||||
conn->handler->connection_check(conn, CONNCHECK_KEEPALIVE);
|
||||
}
|
||||
|
||||
return 0; /* continue iteration */
|
||||
}
|
||||
|
||||
static CURLcode upkeep(struct conncache *conn_cache, void *data)
|
||||
{
|
||||
/* Loop over every connection and make connection alive. */
|
||||
Curl_conncache_foreach(data,
|
||||
conn_cache,
|
||||
data,
|
||||
conn_upkeep);
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs connection upkeep for the given session handle.
|
||||
*/
|
||||
@ -1148,7 +1176,7 @@ CURLcode curl_easy_upkeep(struct Curl_easy *data)
|
||||
|
||||
if(data->multi_easy) {
|
||||
/* Use the common function to keep connections alive. */
|
||||
return Curl_upkeep(&data->multi_easy->conn_cache, data);
|
||||
return upkeep(&data->multi_easy->conn_cache, data);
|
||||
}
|
||||
else {
|
||||
/* No connections, so just return success */
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2019, 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
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2020, 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
|
||||
@ -136,7 +136,7 @@ static CURLcode file_connect(struct connectdata *conn, bool *done)
|
||||
struct Curl_easy *data = conn->data;
|
||||
char *real_path;
|
||||
struct FILEPROTO *file = data->req.protop;
|
||||
int fd;
|
||||
int fd = -1;
|
||||
#ifdef DOS_FILESYSTEM
|
||||
size_t i;
|
||||
char *actual_path;
|
||||
@ -181,7 +181,9 @@ static CURLcode file_connect(struct connectdata *conn, bool *done)
|
||||
return CURLE_URL_MALFORMAT;
|
||||
}
|
||||
|
||||
fd = open_readonly(actual_path, O_RDONLY|O_BINARY);
|
||||
if(strncmp("\\\\", actual_path, 2))
|
||||
/* refuse to open path that starts with two backslashes */
|
||||
fd = open_readonly(actual_path, O_RDONLY|O_BINARY);
|
||||
file->path = actual_path;
|
||||
#else
|
||||
if(memchr(real_path, 0, real_path_len)) {
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2019, 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
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2020, 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
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2020, 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
|
||||
@ -55,7 +55,6 @@
|
||||
#include "transfer.h"
|
||||
#include "escape.h"
|
||||
#include "http.h" /* for HTTP proxy tunnel stuff */
|
||||
#include "socks.h"
|
||||
#include "ftp.h"
|
||||
#include "fileinfo.h"
|
||||
#include "ftplistparser.h"
|
||||
@ -78,6 +77,7 @@
|
||||
#include "warnless.h"
|
||||
#include "http_proxy.h"
|
||||
#include "non-ascii.h"
|
||||
#include "socks.h"
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
@ -132,10 +132,8 @@ static CURLcode ftp_connect(struct connectdata *conn, bool *done);
|
||||
static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection);
|
||||
static CURLcode ftp_do_more(struct connectdata *conn, int *completed);
|
||||
static CURLcode ftp_multi_statemach(struct connectdata *conn, bool *done);
|
||||
static int ftp_getsock(struct connectdata *conn, curl_socket_t *socks,
|
||||
int numsocks);
|
||||
static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks,
|
||||
int numsocks);
|
||||
static int ftp_getsock(struct connectdata *conn, curl_socket_t *socks);
|
||||
static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks);
|
||||
static CURLcode ftp_doing(struct connectdata *conn,
|
||||
bool *dophase_done);
|
||||
static CURLcode ftp_setup_connection(struct connectdata * conn);
|
||||
@ -255,18 +253,6 @@ static void freedirs(struct ftp_conn *ftpc)
|
||||
Curl_safefree(ftpc->newhost);
|
||||
}
|
||||
|
||||
/* Returns non-zero if the given string contains CR (\r) or LF (\n),
|
||||
which are not allowed within RFC 959 <string>.
|
||||
Note: The input string is in the client's encoding which might
|
||||
not be ASCII, so escape sequences \r & \n must be used instead
|
||||
of hex values 0x0d & 0x0a.
|
||||
*/
|
||||
static bool isBadFtpString(const char *string)
|
||||
{
|
||||
return ((NULL != strchr(string, '\r')) ||
|
||||
(NULL != strchr(string, '\n'))) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* AcceptServerConnect()
|
||||
@ -305,7 +291,7 @@ static CURLcode AcceptServerConnect(struct connectdata *conn)
|
||||
|
||||
conn->sock[SECONDARYSOCKET] = s;
|
||||
(void)curlx_nonblock(s, TRUE); /* enable non-blocking */
|
||||
conn->sock_accepted[SECONDARYSOCKET] = TRUE;
|
||||
conn->sock_accepted = TRUE;
|
||||
|
||||
if(data->set.fsockopt) {
|
||||
int error = 0;
|
||||
@ -382,7 +368,7 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received)
|
||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||
struct pingpong *pp = &ftpc->pp;
|
||||
int result;
|
||||
time_t timeout_ms;
|
||||
timediff_t timeout_ms;
|
||||
ssize_t nread;
|
||||
int ftpcode;
|
||||
|
||||
@ -493,7 +479,7 @@ static CURLcode InitiateTransfer(struct connectdata *conn)
|
||||
static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected)
|
||||
{
|
||||
struct Curl_easy *data = conn->data;
|
||||
time_t timeout_ms;
|
||||
timediff_t timeout_ms;
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
*connected = FALSE;
|
||||
@ -525,7 +511,7 @@ static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected)
|
||||
}
|
||||
else {
|
||||
/* Add timeout to multi handle and break out of the loop */
|
||||
if(!result && *connected == FALSE) {
|
||||
if(*connected == FALSE) {
|
||||
Curl_expire(data, data->set.accepttimeout > 0 ?
|
||||
data->set.accepttimeout: DEFAULT_ACCEPT_TIMEOUT, 0);
|
||||
}
|
||||
@ -565,10 +551,8 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
|
||||
#ifdef HAVE_GSSAPI
|
||||
char * const buf = data->state.buffer;
|
||||
#endif
|
||||
CURLcode result = CURLE_OK;
|
||||
int code;
|
||||
|
||||
result = Curl_pp_readresp(sockfd, pp, &code, size);
|
||||
CURLcode result = Curl_pp_readresp(sockfd, pp, &code, size);
|
||||
|
||||
#if defined(HAVE_GSSAPI)
|
||||
/* handle the security-oriented responses 6xx ***/
|
||||
@ -789,9 +773,8 @@ static void _state(struct connectdata *conn,
|
||||
static CURLcode ftp_state_user(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result;
|
||||
struct FTP *ftp = conn->data->req.protop;
|
||||
/* send USER */
|
||||
PPSENDF(&conn->proto.ftpc.pp, "USER %s", ftp->user?ftp->user:"");
|
||||
PPSENDF(&conn->proto.ftpc.pp, "USER %s", conn->user?conn->user:"");
|
||||
|
||||
state(conn, FTP_USER);
|
||||
conn->data->state.ftp_trying_alternative = FALSE;
|
||||
@ -812,26 +795,24 @@ static CURLcode ftp_state_pwd(struct connectdata *conn)
|
||||
|
||||
/* For the FTP "protocol connect" and "doing" phases only */
|
||||
static int ftp_getsock(struct connectdata *conn,
|
||||
curl_socket_t *socks,
|
||||
int numsocks)
|
||||
curl_socket_t *socks)
|
||||
{
|
||||
return Curl_pp_getsock(&conn->proto.ftpc.pp, socks, numsocks);
|
||||
return Curl_pp_getsock(&conn->proto.ftpc.pp, socks);
|
||||
}
|
||||
|
||||
/* For the FTP "DO_MORE" phase only */
|
||||
static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks,
|
||||
int numsocks)
|
||||
static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks)
|
||||
{
|
||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||
|
||||
if(!numsocks)
|
||||
return GETSOCK_BLANK;
|
||||
|
||||
/* When in DO_MORE state, we could be either waiting for us to connect to a
|
||||
* remote site, or we could wait for that site to connect to us. Or just
|
||||
* handle ordinary commands.
|
||||
*/
|
||||
|
||||
if(SOCKS_STATE(conn->cnnct.state))
|
||||
return Curl_SOCKS_getsock(conn, socks, SECONDARYSOCKET);
|
||||
|
||||
if(FTP_STOP == ftpc->state) {
|
||||
int bits = GETSOCK_READSOCK(0);
|
||||
|
||||
@ -858,7 +839,7 @@ static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks,
|
||||
|
||||
return bits;
|
||||
}
|
||||
return Curl_pp_getsock(&conn->proto.ftpc.pp, socks, numsocks);
|
||||
return Curl_pp_getsock(&conn->proto.ftpc.pp, socks);
|
||||
}
|
||||
|
||||
/* This is called after the FTP_QUOTE state is passed.
|
||||
@ -876,6 +857,10 @@ static CURLcode ftp_state_cwd(struct connectdata *conn)
|
||||
/* already done and fine */
|
||||
result = ftp_state_mdtm(conn);
|
||||
else {
|
||||
/* FTPFILE_NOCWD with full path: expect ftpc->cwddone! */
|
||||
DEBUGASSERT((conn->data->set.ftp_filemethod != FTPFILE_NOCWD) ||
|
||||
!(ftpc->dirdepth && ftpc->dirs[0][0] == '/'));
|
||||
|
||||
ftpc->count2 = 0; /* count2 counts failed CWDs */
|
||||
|
||||
/* count3 is set to allow a MKD to fail once. In the case when first CWD
|
||||
@ -883,10 +868,9 @@ static CURLcode ftp_state_cwd(struct connectdata *conn)
|
||||
dir) this then allows for a second try to CWD to it */
|
||||
ftpc->count3 = (conn->data->set.ftp_create_missing_dirs == 2)?1:0;
|
||||
|
||||
if((conn->data->set.ftp_filemethod == FTPFILE_NOCWD) && !ftpc->cwdcount)
|
||||
/* No CWD necessary */
|
||||
result = ftp_state_mdtm(conn);
|
||||
else if(conn->bits.reuse && ftpc->entrypath) {
|
||||
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
|
||||
transfer is taking place, we must first get back to the original dir
|
||||
where we ended up after login: */
|
||||
@ -926,7 +910,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
|
||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||
struct Curl_easy *data = conn->data;
|
||||
curl_socket_t portsock = CURL_SOCKET_BAD;
|
||||
char myhost[256] = "";
|
||||
char myhost[MAX_IPADR_LEN + 1] = "";
|
||||
|
||||
struct Curl_sockaddr_storage ss;
|
||||
Curl_addrinfo *res, *ai;
|
||||
@ -937,9 +921,8 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
|
||||
#ifdef ENABLE_IPV6
|
||||
struct sockaddr_in6 * const sa6 = (void *)sa;
|
||||
#endif
|
||||
char tmp[1024];
|
||||
static const char mode[][5] = { "EPRT", "PORT" };
|
||||
int rc;
|
||||
enum resolve_t rc;
|
||||
int error;
|
||||
char *host = NULL;
|
||||
char *string_ftpport = data->set.str[STRING_FTPPORT];
|
||||
@ -1252,8 +1235,10 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
|
||||
break;
|
||||
}
|
||||
if(PORT == fcmd) {
|
||||
/* large enough for [IP address],[num],[num] */
|
||||
char target[sizeof(myhost) + 20];
|
||||
char *source = myhost;
|
||||
char *dest = tmp;
|
||||
char *dest = target;
|
||||
|
||||
/* translate x.x.x.x to x,x,x,x */
|
||||
while(source && *source) {
|
||||
@ -1267,7 +1252,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
|
||||
*dest = 0;
|
||||
msnprintf(dest, 20, ",%d,%d", (int)(port>>8), (int)(port&0xff));
|
||||
|
||||
result = Curl_pp_sendf(&ftpc->pp, "%s %s", mode[fcmd], tmp);
|
||||
result = Curl_pp_sendf(&ftpc->pp, "%s %s", mode[fcmd], target);
|
||||
if(result) {
|
||||
failf(data, "Failure sending PORT command: %s",
|
||||
curl_easy_strerror(result));
|
||||
@ -1445,31 +1430,37 @@ static CURLcode ftp_state_list(struct connectdata *conn)
|
||||
servers either... */
|
||||
|
||||
/*
|
||||
if FTPFILE_NOCWD was specified, we are currently in
|
||||
the user's home directory, so we should add the path
|
||||
if FTPFILE_NOCWD was specified, we should add the path
|
||||
as argument for the LIST / NLST / or custom command.
|
||||
Whether the server will support this, is uncertain.
|
||||
|
||||
The other ftp_filemethods will CWD into dir/dir/ first and
|
||||
then just do LIST (in that case: nothing to do here)
|
||||
*/
|
||||
char *cmd, *lstArg, *slashPos;
|
||||
const char *inpath = ftp->path;
|
||||
char *lstArg = NULL;
|
||||
char *cmd;
|
||||
|
||||
lstArg = NULL;
|
||||
if((data->set.ftp_filemethod == FTPFILE_NOCWD) &&
|
||||
inpath && inpath[0] && strchr(inpath, '/')) {
|
||||
size_t n = strlen(inpath);
|
||||
|
||||
/* Check if path does not end with /, as then we cut off the file part */
|
||||
if(inpath[n - 1] != '/') {
|
||||
/* chop off the file part if format is dir/dir/file */
|
||||
slashPos = strrchr(inpath, '/');
|
||||
n = slashPos - inpath;
|
||||
}
|
||||
result = Curl_urldecode(data, inpath, n, &lstArg, NULL, TRUE);
|
||||
if((data->set.ftp_filemethod == FTPFILE_NOCWD) && ftp->path) {
|
||||
/* url-decode before evaluation: e.g. paths starting/ending with %2f */
|
||||
const char *slashPos = NULL;
|
||||
char *rawPath = NULL;
|
||||
result = Curl_urldecode(data, ftp->path, 0, &rawPath, NULL, TRUE);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
slashPos = strrchr(rawPath, '/');
|
||||
if(slashPos) {
|
||||
/* chop off the file part if format is dir/file otherwise remove
|
||||
the trailing slash for dir/dir/ except for absolute path / */
|
||||
size_t n = slashPos - rawPath;
|
||||
if(n == 0)
|
||||
++n;
|
||||
|
||||
lstArg = rawPath;
|
||||
lstArg[n] = '\0';
|
||||
}
|
||||
else
|
||||
free(rawPath);
|
||||
}
|
||||
|
||||
cmd = aprintf("%s%s%s",
|
||||
@ -1478,15 +1469,12 @@ static CURLcode ftp_state_list(struct connectdata *conn)
|
||||
(data->set.ftp_list_only?"NLST":"LIST"),
|
||||
lstArg? " ": "",
|
||||
lstArg? lstArg: "");
|
||||
free(lstArg);
|
||||
|
||||
if(!cmd) {
|
||||
free(lstArg);
|
||||
if(!cmd)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", cmd);
|
||||
|
||||
free(lstArg);
|
||||
free(cmd);
|
||||
|
||||
if(result)
|
||||
@ -1499,24 +1487,14 @@ static CURLcode ftp_state_list(struct connectdata *conn)
|
||||
|
||||
static CURLcode ftp_state_retr_prequote(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
/* We've sent the TYPE, now we must send the list of prequote strings */
|
||||
|
||||
result = ftp_state_quote(conn, TRUE, FTP_RETR_PREQUOTE);
|
||||
|
||||
return result;
|
||||
return ftp_state_quote(conn, TRUE, FTP_RETR_PREQUOTE);
|
||||
}
|
||||
|
||||
static CURLcode ftp_state_stor_prequote(struct connectdata *conn)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
/* We've sent the TYPE, now we must send the list of prequote strings */
|
||||
|
||||
result = ftp_state_quote(conn, TRUE, FTP_STOR_PREQUOTE);
|
||||
|
||||
return result;
|
||||
return ftp_state_quote(conn, TRUE, FTP_STOR_PREQUOTE);
|
||||
}
|
||||
|
||||
static CURLcode ftp_state_type(struct connectdata *conn)
|
||||
@ -1819,7 +1797,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
|
||||
CURLcode result;
|
||||
struct Curl_easy *data = conn->data;
|
||||
struct Curl_dns_entry *addr = NULL;
|
||||
int rc;
|
||||
enum resolve_t rc;
|
||||
unsigned short connectport; /* the local port connect() should use! */
|
||||
char *str = &data->state.buffer[4]; /* start on the first letter */
|
||||
|
||||
@ -2052,13 +2030,11 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
|
||||
&year, &month, &day, &hour, &minute, &second)) {
|
||||
/* we have a time, reformat it */
|
||||
char timebuf[24];
|
||||
time_t secs = time(NULL);
|
||||
|
||||
msnprintf(timebuf, sizeof(timebuf),
|
||||
"%04d%02d%02d %02d:%02d:%02d GMT",
|
||||
year, month, day, hour, minute, second);
|
||||
/* now, convert this into a time() value: */
|
||||
data->info.filetime = curl_getdate(timebuf, &secs);
|
||||
data->info.filetime = Curl_getdate_capped(timebuf);
|
||||
}
|
||||
|
||||
#ifdef CURL_FTP_HTTPSTYLE_HEAD
|
||||
@ -2261,9 +2237,25 @@ static CURLcode ftp_state_size_resp(struct connectdata *conn,
|
||||
char *buf = data->state.buffer;
|
||||
|
||||
/* get the size from the ascii string: */
|
||||
if(ftpcode == 213)
|
||||
if(ftpcode == 213) {
|
||||
/* To allow servers to prepend "rubbish" in the response string, we scan
|
||||
for all the digits at the end of the response and parse only those as a
|
||||
number. */
|
||||
char *start = &buf[4];
|
||||
char *fdigit = strchr(start, '\r');
|
||||
if(fdigit) {
|
||||
do
|
||||
fdigit--;
|
||||
while(ISDIGIT(*fdigit) && (fdigit > start));
|
||||
if(!ISDIGIT(*fdigit))
|
||||
fdigit++;
|
||||
}
|
||||
else
|
||||
fdigit = start;
|
||||
/* ignores parsing errors, which will make the size remain unknown */
|
||||
(void)curlx_strtoofft(buf + 4, NULL, 0, &filesize);
|
||||
(void)curlx_strtoofft(fdigit, NULL, 0, &filesize);
|
||||
|
||||
}
|
||||
|
||||
if(instate == FTP_SIZE) {
|
||||
#ifdef CURL_FTP_HTTPSTYLE_HEAD
|
||||
@ -2527,7 +2519,6 @@ static CURLcode ftp_state_user_resp(struct connectdata *conn,
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct Curl_easy *data = conn->data;
|
||||
struct FTP *ftp = data->req.protop;
|
||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||
(void)instate; /* no use for this yet */
|
||||
|
||||
@ -2535,7 +2526,7 @@ static CURLcode ftp_state_user_resp(struct connectdata *conn,
|
||||
if((ftpcode == 331) && (ftpc->state == FTP_USER)) {
|
||||
/* 331 Password required for ...
|
||||
(the server requires to send the user's password too) */
|
||||
PPSENDF(&ftpc->pp, "PASS %s", ftp->passwd?ftp->passwd:"");
|
||||
PPSENDF(&ftpc->pp, "PASS %s", conn->passwd?conn->passwd:"");
|
||||
state(conn, FTP_PASS);
|
||||
}
|
||||
else if(ftpcode/100 == 2) {
|
||||
@ -3134,7 +3125,8 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
|
||||
ssize_t nread;
|
||||
int ftpcode;
|
||||
CURLcode result = CURLE_OK;
|
||||
char *path = NULL;
|
||||
char *rawPath = NULL;
|
||||
size_t pathLen = 0;
|
||||
|
||||
if(!ftp)
|
||||
return CURLE_OK;
|
||||
@ -3172,9 +3164,6 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
|
||||
break;
|
||||
}
|
||||
|
||||
/* now store a copy of the directory we are in */
|
||||
free(ftpc->prevpath);
|
||||
|
||||
if(data->state.wildcardmatch) {
|
||||
if(data->set.chunk_end && ftpc->file) {
|
||||
Curl_set_in_callback(data, true);
|
||||
@ -3185,41 +3174,41 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
|
||||
}
|
||||
|
||||
if(!result)
|
||||
/* get the "raw" path */
|
||||
result = Curl_urldecode(data, ftp->path, 0, &path, NULL, TRUE);
|
||||
/* get the url-decoded "raw" path */
|
||||
result = Curl_urldecode(data, ftp->path, 0, &rawPath, &pathLen, TRUE);
|
||||
if(result) {
|
||||
/* We can limp along anyway (and should try to since we may already be in
|
||||
* the error path) */
|
||||
ftpc->ctl_valid = FALSE; /* mark control connection as bad */
|
||||
connclose(conn, "FTP: out of memory!"); /* mark for connection closure */
|
||||
free(ftpc->prevpath);
|
||||
ftpc->prevpath = NULL; /* no path remembering */
|
||||
}
|
||||
else {
|
||||
size_t flen = ftpc->file?strlen(ftpc->file):0; /* file is "raw" already */
|
||||
size_t dlen = strlen(path)-flen;
|
||||
if(!ftpc->cwdfail) {
|
||||
ftpc->prevmethod = data->set.ftp_filemethod;
|
||||
if(dlen && (data->set.ftp_filemethod != FTPFILE_NOCWD)) {
|
||||
ftpc->prevpath = path;
|
||||
if(flen)
|
||||
/* if 'path' is not the whole string */
|
||||
ftpc->prevpath[dlen] = 0; /* terminate */
|
||||
else { /* remember working directory for connection reuse */
|
||||
if((data->set.ftp_filemethod == FTPFILE_NOCWD) && (rawPath[0] == '/'))
|
||||
free(rawPath); /* full path => no CWDs happened => keep ftpc->prevpath */
|
||||
else {
|
||||
free(ftpc->prevpath);
|
||||
|
||||
if(!ftpc->cwdfail) {
|
||||
if(data->set.ftp_filemethod == FTPFILE_NOCWD)
|
||||
pathLen = 0; /* relative path => working directory is FTP home */
|
||||
else
|
||||
pathLen -= ftpc->file?strlen(ftpc->file):0; /* file is url-decoded */
|
||||
|
||||
rawPath[pathLen] = '\0';
|
||||
ftpc->prevpath = rawPath;
|
||||
}
|
||||
else {
|
||||
free(path);
|
||||
/* we never changed dir */
|
||||
ftpc->prevpath = strdup("");
|
||||
if(!ftpc->prevpath)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
free(rawPath);
|
||||
ftpc->prevpath = NULL; /* no path */
|
||||
}
|
||||
if(ftpc->prevpath)
|
||||
infof(data, "Remembering we are in dir \"%s\"\n", ftpc->prevpath);
|
||||
}
|
||||
else {
|
||||
ftpc->prevpath = NULL; /* no path */
|
||||
free(path);
|
||||
}
|
||||
|
||||
if(ftpc->prevpath)
|
||||
infof(data, "Remembering we are in dir \"%s\"\n", ftpc->prevpath);
|
||||
}
|
||||
|
||||
/* free the dir tree and file parts */
|
||||
freedirs(ftpc);
|
||||
|
||||
@ -3532,14 +3521,13 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
|
||||
|
||||
/* if we got an error or if we don't wait for a data connection return
|
||||
immediately */
|
||||
if(result || (ftpc->wait_data_conn != TRUE))
|
||||
if(result || !ftpc->wait_data_conn)
|
||||
return result;
|
||||
|
||||
if(ftpc->wait_data_conn)
|
||||
/* if we reach the end of the FTP state machine here, *complete will be
|
||||
TRUE but so is ftpc->wait_data_conn, which says we need to wait for
|
||||
the data connection and therefore we're not actually complete */
|
||||
*completep = 0;
|
||||
/* if we reach the end of the FTP state machine here, *complete will be
|
||||
TRUE but so is ftpc->wait_data_conn, which says we need to wait for the
|
||||
data connection and therefore we're not actually complete */
|
||||
*completep = 0;
|
||||
}
|
||||
|
||||
if(ftp->transfer <= FTPTRANSFER_INFO) {
|
||||
@ -3573,13 +3561,8 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
|
||||
return result;
|
||||
|
||||
result = ftp_multi_statemach(conn, &complete);
|
||||
if(ftpc->wait_data_conn)
|
||||
/* if we reach the end of the FTP state machine here, *complete will be
|
||||
TRUE but so is ftpc->wait_data_conn, which says we need to wait for
|
||||
the data connection and therefore we're not actually complete */
|
||||
*completep = 0;
|
||||
else
|
||||
*completep = (int)complete;
|
||||
/* ftpc->wait_data_conn is always false here */
|
||||
*completep = (int)complete;
|
||||
}
|
||||
else {
|
||||
/* download */
|
||||
@ -3619,10 +3602,8 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
|
||||
return result;
|
||||
}
|
||||
|
||||
if(!result && (ftp->transfer != FTPTRANSFER_BODY))
|
||||
/* no data to transfer. FIX: it feels like a kludge to have this here
|
||||
too! */
|
||||
Curl_setup_transfer(data, -1, -1, FALSE, -1);
|
||||
/* no data to transfer */
|
||||
Curl_setup_transfer(data, -1, -1, FALSE, -1);
|
||||
|
||||
if(!ftpc->wait_data_conn) {
|
||||
/* no waiting for the data connection so this is now complete */
|
||||
@ -4100,186 +4081,142 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
|
||||
/* the ftp struct is already inited in ftp_connect() */
|
||||
struct FTP *ftp = data->req.protop;
|
||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||
const char *slash_pos; /* position of the first '/' char in curpos */
|
||||
const char *path_to_use = ftp->path;
|
||||
const char *cur_pos;
|
||||
const char *filename = NULL;
|
||||
|
||||
cur_pos = path_to_use; /* current position in path. point at the begin of
|
||||
next path component */
|
||||
const char *slashPos = NULL;
|
||||
const char *fileName = NULL;
|
||||
CURLcode result = CURLE_OK;
|
||||
char *rawPath = NULL; /* url-decoded "raw" path */
|
||||
size_t pathLen = 0;
|
||||
|
||||
ftpc->ctl_valid = FALSE;
|
||||
ftpc->cwdfail = FALSE;
|
||||
|
||||
/* url-decode ftp path before further evaluation */
|
||||
result = Curl_urldecode(data, ftp->path, 0, &rawPath, &pathLen, TRUE);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
switch(data->set.ftp_filemethod) {
|
||||
case FTPFILE_NOCWD:
|
||||
/* fastest, but less standard-compliant */
|
||||
case FTPFILE_NOCWD: /* fastest, but less standard-compliant */
|
||||
|
||||
/*
|
||||
The best time to check whether the path is a file or directory is right
|
||||
here. so:
|
||||
|
||||
the first condition in the if() right here, is there just in case
|
||||
someone decides to set path to NULL one day
|
||||
*/
|
||||
if(path_to_use[0] &&
|
||||
(path_to_use[strlen(path_to_use) - 1] != '/') )
|
||||
filename = path_to_use; /* this is a full file path */
|
||||
/*
|
||||
else {
|
||||
ftpc->file is not used anywhere other than for operations on a file.
|
||||
In other words, never for directory operations.
|
||||
So we can safely leave filename as NULL here and use it as a
|
||||
argument in dir/file decisions.
|
||||
}
|
||||
*/
|
||||
break;
|
||||
|
||||
case FTPFILE_SINGLECWD:
|
||||
/* get the last slash */
|
||||
if(!path_to_use[0]) {
|
||||
/* no dir, no file */
|
||||
ftpc->dirdepth = 0;
|
||||
if((pathLen > 0) && (rawPath[pathLen - 1] != '/'))
|
||||
fileName = rawPath; /* this is a full file path */
|
||||
/*
|
||||
else: ftpc->file is not used anywhere other than for operations on
|
||||
a file. In other words, never for directory operations.
|
||||
So we can safely leave filename as NULL here and use it as a
|
||||
argument in dir/file decisions.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
slash_pos = strrchr(cur_pos, '/');
|
||||
if(slash_pos || !*cur_pos) {
|
||||
size_t dirlen = slash_pos-cur_pos;
|
||||
CURLcode result;
|
||||
|
||||
ftpc->dirs = calloc(1, sizeof(ftpc->dirs[0]));
|
||||
if(!ftpc->dirs)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
case FTPFILE_SINGLECWD:
|
||||
slashPos = strrchr(rawPath, '/');
|
||||
if(slashPos) {
|
||||
/* get path before last slash, except for / */
|
||||
size_t dirlen = slashPos - rawPath;
|
||||
if(dirlen == 0)
|
||||
dirlen++;
|
||||
|
||||
if(!dirlen)
|
||||
dirlen++;
|
||||
ftpc->dirs = calloc(1, sizeof(ftpc->dirs[0]));
|
||||
if(!ftpc->dirs) {
|
||||
free(rawPath);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
result = Curl_urldecode(conn->data, slash_pos ? cur_pos : "/",
|
||||
slash_pos ? dirlen : 1,
|
||||
&ftpc->dirs[0], NULL,
|
||||
TRUE);
|
||||
if(result) {
|
||||
freedirs(ftpc);
|
||||
return result;
|
||||
ftpc->dirs[0] = calloc(1, dirlen + 1);
|
||||
if(!ftpc->dirs[0]) {
|
||||
free(rawPath);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
strncpy(ftpc->dirs[0], rawPath, dirlen);
|
||||
ftpc->dirdepth = 1; /* we consider it to be a single dir */
|
||||
fileName = slashPos + 1; /* rest is file name */
|
||||
}
|
||||
ftpc->dirdepth = 1; /* we consider it to be a single dir */
|
||||
filename = slash_pos ? slash_pos + 1 : cur_pos; /* rest is file name */
|
||||
}
|
||||
else
|
||||
filename = cur_pos; /* this is a file name only */
|
||||
break;
|
||||
else
|
||||
fileName = rawPath; /* file name only (or empty) */
|
||||
break;
|
||||
|
||||
default: /* allow pretty much anything */
|
||||
case FTPFILE_MULTICWD:
|
||||
ftpc->dirdepth = 0;
|
||||
ftpc->diralloc = 5; /* default dir depth to allocate */
|
||||
ftpc->dirs = calloc(ftpc->diralloc, sizeof(ftpc->dirs[0]));
|
||||
if(!ftpc->dirs)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
default: /* allow pretty much anything */
|
||||
case FTPFILE_MULTICWD: {
|
||||
/* current position: begin of next path component */
|
||||
const char *curPos = rawPath;
|
||||
|
||||
/* we have a special case for listing the root dir only */
|
||||
if(!strcmp(path_to_use, "/")) {
|
||||
cur_pos++; /* make it point to the zero byte */
|
||||
ftpc->dirs[0] = strdup("/");
|
||||
ftpc->dirdepth++;
|
||||
}
|
||||
else {
|
||||
/* parse the URL path into separate path components */
|
||||
while((slash_pos = strchr(cur_pos, '/')) != NULL) {
|
||||
/* 1 or 0 pointer offset to indicate absolute directory */
|
||||
ssize_t absolute_dir = ((cur_pos - ftp->path > 0) &&
|
||||
(ftpc->dirdepth == 0))?1:0;
|
||||
int dirAlloc = 0; /* number of entries allocated for the 'dirs' array */
|
||||
const char *str = rawPath;
|
||||
for(; *str != 0; ++str)
|
||||
if (*str == '/')
|
||||
++dirAlloc;
|
||||
|
||||
if(dirAlloc > 0) {
|
||||
ftpc->dirs = calloc(dirAlloc, sizeof(ftpc->dirs[0]));
|
||||
if(!ftpc->dirs) {
|
||||
free(rawPath);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
/* parse the URL path into separate path components */
|
||||
while((slashPos = strchr(curPos, '/')) != NULL) {
|
||||
size_t compLen = slashPos - curPos;
|
||||
|
||||
/* path starts with a slash: add that as a directory */
|
||||
if((compLen == 0) && (ftpc->dirdepth == 0))
|
||||
++compLen;
|
||||
|
||||
/* seek out the next path component */
|
||||
if(slash_pos-cur_pos) {
|
||||
/* we skip empty path components, like "x//y" since the FTP command
|
||||
CWD requires a parameter and a non-existent parameter a) doesn't
|
||||
work on many servers and b) has no effect on the others. */
|
||||
size_t len = slash_pos - cur_pos + absolute_dir;
|
||||
CURLcode result =
|
||||
Curl_urldecode(conn->data, cur_pos - absolute_dir, len,
|
||||
&ftpc->dirs[ftpc->dirdepth], NULL,
|
||||
TRUE);
|
||||
if(result) {
|
||||
freedirs(ftpc);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else {
|
||||
cur_pos = slash_pos + 1; /* jump to the rest of the string */
|
||||
if(!ftpc->dirdepth) {
|
||||
/* path starts with a slash, add that as a directory */
|
||||
ftpc->dirs[ftpc->dirdepth] = strdup("/");
|
||||
if(!ftpc->dirs[ftpc->dirdepth++]) { /* run out of memory ... */
|
||||
failf(data, "no memory");
|
||||
freedirs(ftpc);
|
||||
if(compLen > 0) {
|
||||
char *comp = calloc(1, compLen + 1);
|
||||
if(!comp) {
|
||||
free(rawPath);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
strncpy(comp, curPos, compLen);
|
||||
ftpc->dirs[ftpc->dirdepth++] = comp;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
cur_pos = slash_pos + 1; /* jump to the rest of the string */
|
||||
if(++ftpc->dirdepth >= ftpc->diralloc) {
|
||||
/* enlarge array */
|
||||
char **bigger;
|
||||
ftpc->diralloc *= 2; /* double the size each time */
|
||||
bigger = realloc(ftpc->dirs, ftpc->diralloc * sizeof(ftpc->dirs[0]));
|
||||
if(!bigger) {
|
||||
freedirs(ftpc);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
ftpc->dirs = bigger;
|
||||
curPos = slashPos + 1;
|
||||
}
|
||||
}
|
||||
DEBUGASSERT(ftpc->dirdepth <= dirAlloc);
|
||||
fileName = curPos; /* the rest is the file name (or empty) */
|
||||
}
|
||||
filename = cur_pos; /* the rest is the file name */
|
||||
break;
|
||||
} /* switch */
|
||||
|
||||
if(filename && *filename) {
|
||||
CURLcode result =
|
||||
Curl_urldecode(conn->data, filename, 0, &ftpc->file, NULL, TRUE);
|
||||
|
||||
if(result) {
|
||||
freedirs(ftpc);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
if(fileName && *fileName)
|
||||
ftpc->file = strdup(fileName);
|
||||
else
|
||||
ftpc->file = NULL; /* instead of point to a zero byte, we make it a NULL
|
||||
pointer */
|
||||
ftpc->file = NULL; /* instead of point to a zero byte,
|
||||
we make it a NULL pointer */
|
||||
|
||||
if(data->set.upload && !ftpc->file && (ftp->transfer == FTPTRANSFER_BODY)) {
|
||||
/* We need a file name when uploading. Return error! */
|
||||
failf(data, "Uploading to a URL without a file name!");
|
||||
free(rawPath);
|
||||
return CURLE_URL_MALFORMAT;
|
||||
}
|
||||
|
||||
ftpc->cwddone = FALSE; /* default to not done */
|
||||
|
||||
if(ftpc->prevpath) {
|
||||
/* prevpath is "raw" so we convert the input path before we compare the
|
||||
strings */
|
||||
size_t dlen;
|
||||
char *path;
|
||||
CURLcode result =
|
||||
Curl_urldecode(conn->data, ftp->path, 0, &path, &dlen, TRUE);
|
||||
if(result) {
|
||||
freedirs(ftpc);
|
||||
return result;
|
||||
}
|
||||
if((data->set.ftp_filemethod == FTPFILE_NOCWD) && (rawPath[0] == '/'))
|
||||
ftpc->cwddone = TRUE; /* skip CWD for absolute paths */
|
||||
else { /* newly created FTP connections are already in entry path */
|
||||
const char *oldPath = conn->bits.reuse ? ftpc->prevpath : "";
|
||||
if(oldPath) {
|
||||
size_t n = pathLen;
|
||||
if(data->set.ftp_filemethod == FTPFILE_NOCWD)
|
||||
n = 0; /* CWD to entry for relative paths */
|
||||
else
|
||||
n -= ftpc->file?strlen(ftpc->file):0;
|
||||
|
||||
dlen -= ftpc->file?strlen(ftpc->file):0;
|
||||
if((dlen == strlen(ftpc->prevpath)) &&
|
||||
!strncmp(path, ftpc->prevpath, dlen) &&
|
||||
(ftpc->prevmethod == data->set.ftp_filemethod)) {
|
||||
infof(data, "Request has same path as previous transfer\n");
|
||||
ftpc->cwddone = TRUE;
|
||||
if((strlen(oldPath) == n) && !strncmp(rawPath, oldPath, n)) {
|
||||
infof(data, "Request has same path as previous transfer\n");
|
||||
ftpc->cwddone = TRUE;
|
||||
}
|
||||
}
|
||||
free(path);
|
||||
}
|
||||
|
||||
free(rawPath);
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
@ -4423,18 +4360,6 @@ static CURLcode ftp_setup_connection(struct connectdata *conn)
|
||||
/* get some initial data into the ftp struct */
|
||||
ftp->transfer = FTPTRANSFER_BODY;
|
||||
ftp->downloadsize = 0;
|
||||
|
||||
/* No need to duplicate user+password, the connectdata struct won't change
|
||||
during a session, but we re-init them here since on subsequent inits
|
||||
since the conn struct may have changed or been replaced.
|
||||
*/
|
||||
ftp->user = conn->user;
|
||||
ftp->passwd = conn->passwd;
|
||||
if(isBadFtpString(ftp->user))
|
||||
return CURLE_URL_MALFORMAT;
|
||||
if(isBadFtpString(ftp->passwd))
|
||||
return CURLE_URL_MALFORMAT;
|
||||
|
||||
conn->proto.ftpc.known_filesize = -1; /* unknown size for now */
|
||||
|
||||
return CURLE_OK;
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2020, 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
|
||||
@ -102,8 +102,6 @@ typedef enum {
|
||||
perhaps the Curl_easy is changed between the times the connection is
|
||||
used. */
|
||||
struct FTP {
|
||||
char *user; /* user name string */
|
||||
char *passwd; /* password string */
|
||||
char *path; /* points to the urlpieces struct field */
|
||||
char *pathalloc; /* if non-NULL a pointer to an allocated path */
|
||||
|
||||
@ -121,8 +119,7 @@ struct ftp_conn {
|
||||
char *entrypath; /* the PWD reply when we logged on */
|
||||
char **dirs; /* realloc()ed array for path components */
|
||||
int dirdepth; /* number of entries used in the 'dirs' array */
|
||||
int diralloc; /* number of entries allocated for the 'dirs' array */
|
||||
char *file; /* decoded file */
|
||||
char *file; /* url-decoded file name (or path) */
|
||||
bool dont_check; /* Set to TRUE to prevent the final (post-transfer)
|
||||
file size and 226/250 status check. It should still
|
||||
read the line, just ignore the result. */
|
||||
@ -135,8 +132,7 @@ struct ftp_conn {
|
||||
bool cwdfail; /* set TRUE if a CWD command fails, as then we must prevent
|
||||
caching the current directory */
|
||||
bool wait_data_conn; /* this is set TRUE if data connection is waited */
|
||||
char *prevpath; /* conn->path from the previous transfer */
|
||||
curl_ftpfile prevmethod; /* ftp method in previous transfer */
|
||||
char *prevpath; /* url-decoded conn->path from the previous transfer */
|
||||
char transfertype; /* set by ftp_transfertype for use by Curl_client_write()a
|
||||
and others (A/I or zero) */
|
||||
int count1; /* general purpose counter for the state machine */
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2019, 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
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2019, 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
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2020, 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
|
||||
@ -27,25 +27,48 @@
|
||||
|
||||
#include "memdebug.h"
|
||||
|
||||
static
|
||||
char *GetEnv(const char *variable)
|
||||
static char *GetEnv(const char *variable)
|
||||
{
|
||||
#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP)
|
||||
(void)variable;
|
||||
return NULL;
|
||||
#else
|
||||
#ifdef WIN32
|
||||
char env[MAX_PATH]; /* MAX_PATH is from windef.h */
|
||||
char *temp = getenv(variable);
|
||||
env[0] = '\0';
|
||||
if(temp != NULL)
|
||||
ExpandEnvironmentStringsA(temp, env, sizeof(env));
|
||||
return (env[0] != '\0')?strdup(env):NULL;
|
||||
#elif defined(WIN32)
|
||||
/* This uses Windows API instead of C runtime getenv() to get the environment
|
||||
variable since some changes aren't always visible to the latter. #4774 */
|
||||
char *buf = NULL;
|
||||
char *tmp;
|
||||
DWORD bufsize;
|
||||
DWORD rc = 1;
|
||||
const DWORD max = 32768; /* max env var size from MSCRT source */
|
||||
|
||||
for(;;) {
|
||||
tmp = realloc(buf, rc);
|
||||
if(!tmp) {
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buf = tmp;
|
||||
bufsize = rc;
|
||||
|
||||
/* It's possible for rc to be 0 if the variable was found but empty.
|
||||
Since getenv doesn't make that distinction we ignore it as well. */
|
||||
rc = GetEnvironmentVariableA(variable, buf, bufsize);
|
||||
if(!rc || rc == bufsize || rc > max) {
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* if rc < bufsize then rc is bytes written not including null */
|
||||
if(rc < bufsize)
|
||||
return buf;
|
||||
|
||||
/* else rc is bytes needed, try again */
|
||||
}
|
||||
#else
|
||||
char *env = getenv(variable);
|
||||
return (env && env[0])?strdup(env):NULL;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
char *curl_getenv(const char *v)
|
||||
|
@ -235,6 +235,9 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
|
||||
case 20:
|
||||
*param_longp = CURL_HTTP_VERSION_2_0;
|
||||
break;
|
||||
case 30:
|
||||
*param_longp = CURL_HTTP_VERSION_3;
|
||||
break;
|
||||
default:
|
||||
*param_longp = CURL_HTTP_VERSION_NONE;
|
||||
break;
|
||||
@ -243,7 +246,6 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
|
||||
case CURLINFO_PROTOCOL:
|
||||
*param_longp = data->info.conn_protocol;
|
||||
break;
|
||||
|
||||
default:
|
||||
return CURLE_UNKNOWN_OPTION;
|
||||
}
|
||||
@ -301,7 +303,9 @@ static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
|
||||
case CURLINFO_REDIRECT_TIME_T:
|
||||
*param_offt = data->progress.t_redirect;
|
||||
break;
|
||||
|
||||
case CURLINFO_RETRY_AFTER:
|
||||
*param_offt = data->info.retry_after;
|
||||
break;
|
||||
default:
|
||||
return CURLE_UNKNOWN_OPTION;
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2019, 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
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2019, 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
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2019, 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
|
||||
@ -80,7 +80,7 @@ int Curl_hash_delete(struct curl_hash *h, void *key, size_t key_len);
|
||||
void *Curl_hash_pick(struct curl_hash *, void *key, size_t key_len);
|
||||
void Curl_hash_apply(struct curl_hash *h, void *user,
|
||||
void (*cb)(void *user, void *ptr));
|
||||
int Curl_hash_count(struct curl_hash *h);
|
||||
#define Curl_hash_count(h) ((h)->size)
|
||||
void Curl_hash_destroy(struct curl_hash *h);
|
||||
void Curl_hash_clean(struct curl_hash *h);
|
||||
void Curl_hash_clean_with_criterium(struct curl_hash *h, void *user,
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2020, 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
|
||||
@ -30,6 +30,7 @@
|
||||
|
||||
#include "curl_hmac.h"
|
||||
#include "curl_memory.h"
|
||||
#include "warnless.h"
|
||||
|
||||
/* The last #include file should be: */
|
||||
#include "memdebug.h"
|
||||
@ -129,4 +130,40 @@ int Curl_HMAC_final(HMAC_context *ctxt, unsigned char *result)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_hmacit()
|
||||
*
|
||||
* This is used to generate a HMAC hash, for the specified input data, given
|
||||
* the specified hash function and key.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* hashparams [in] - The hash function (Curl_HMAC_MD5).
|
||||
* key [in] - The key to use.
|
||||
* keylen [in] - The length of the key.
|
||||
* data [in] - The data to encrypt.
|
||||
* datalen [in] - The length of the data.
|
||||
* output [in/out] - The output buffer.
|
||||
*
|
||||
* Returns CURLE_OK on success.
|
||||
*/
|
||||
CURLcode Curl_hmacit(const HMAC_params *hashparams,
|
||||
const unsigned char *key, const size_t keylen,
|
||||
const unsigned char *data, const size_t datalen,
|
||||
unsigned char *output)
|
||||
{
|
||||
HMAC_context *ctxt = Curl_HMAC_init(hashparams, key, curlx_uztoui(keylen));
|
||||
|
||||
if(!ctxt)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
||||
/* Update the digest with the given challenge */
|
||||
Curl_HMAC_update(ctxt, data, curlx_uztoui(datalen));
|
||||
|
||||
/* Finalise the digest */
|
||||
Curl_HMAC_final(ctxt, output);
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
#endif /* CURL_DISABLE_CRYPTO_AUTH */
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2019, 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
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2019, 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
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2020, 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
|
||||
@ -59,6 +59,7 @@
|
||||
#include "strerror.h"
|
||||
#include "url.h"
|
||||
#include "inet_ntop.h"
|
||||
#include "inet_pton.h"
|
||||
#include "multiif.h"
|
||||
#include "doh.h"
|
||||
#include "warnless.h"
|
||||
@ -482,16 +483,16 @@ Curl_cache_addr(struct Curl_easy *data,
|
||||
* CURLRESOLV_PENDING (1) = waiting for response, no pointer
|
||||
*/
|
||||
|
||||
int Curl_resolv(struct connectdata *conn,
|
||||
const char *hostname,
|
||||
int port,
|
||||
bool allowDOH,
|
||||
struct Curl_dns_entry **entry)
|
||||
enum resolve_t Curl_resolv(struct connectdata *conn,
|
||||
const char *hostname,
|
||||
int port,
|
||||
bool allowDOH,
|
||||
struct Curl_dns_entry **entry)
|
||||
{
|
||||
struct Curl_dns_entry *dns = NULL;
|
||||
struct Curl_easy *data = conn->data;
|
||||
CURLcode result;
|
||||
int rc = CURLRESOLV_ERROR; /* default to failure */
|
||||
enum resolve_t rc = CURLRESOLV_ERROR; /* default to failure */
|
||||
|
||||
*entry = NULL;
|
||||
|
||||
@ -512,13 +513,11 @@ int Curl_resolv(struct connectdata *conn,
|
||||
if(!dns) {
|
||||
/* The entry was not in the cache. Resolve it to IP address */
|
||||
|
||||
Curl_addrinfo *addr;
|
||||
Curl_addrinfo *addr = NULL;
|
||||
int respwait = 0;
|
||||
|
||||
/* Check what IP specifics the app has requested and if we can provide it.
|
||||
* If not, bail out. */
|
||||
if(!Curl_ipvalid(conn))
|
||||
return CURLRESOLV_ERROR;
|
||||
#ifndef USE_RESOLVE_ON_IPS
|
||||
struct in_addr in;
|
||||
#endif
|
||||
|
||||
/* notify the resolver start callback */
|
||||
if(data->set.resolver_start) {
|
||||
@ -531,20 +530,43 @@ int Curl_resolv(struct connectdata *conn,
|
||||
return CURLRESOLV_ERROR;
|
||||
}
|
||||
|
||||
if(allowDOH && data->set.doh) {
|
||||
addr = Curl_doh(conn, hostname, port, &respwait);
|
||||
#ifndef USE_RESOLVE_ON_IPS
|
||||
/* First check if this is an IPv4 address string */
|
||||
if(Curl_inet_pton(AF_INET, hostname, &in) > 0)
|
||||
/* This is a dotted IP address 123.123.123.123-style */
|
||||
addr = Curl_ip2addr(AF_INET, &in, hostname, port);
|
||||
#ifdef ENABLE_IPV6
|
||||
if(!addr) {
|
||||
struct in6_addr in6;
|
||||
/* check if this is an IPv6 address string */
|
||||
if(Curl_inet_pton(AF_INET6, hostname, &in6) > 0)
|
||||
/* This is an IPv6 address literal */
|
||||
addr = Curl_ip2addr(AF_INET6, &in6, hostname, port);
|
||||
}
|
||||
else {
|
||||
/* If Curl_getaddrinfo() returns NULL, 'respwait' might be set to a
|
||||
non-zero value indicating that we need to wait for the response to the
|
||||
resolve call */
|
||||
addr = Curl_getaddrinfo(conn,
|
||||
#endif /* ENABLE_IPV6 */
|
||||
#endif /* !USE_RESOLVE_ON_IPS */
|
||||
|
||||
if(!addr) {
|
||||
/* Check what IP specifics the app has requested and if we can provide
|
||||
* it. If not, bail out. */
|
||||
if(!Curl_ipvalid(conn))
|
||||
return CURLRESOLV_ERROR;
|
||||
|
||||
if(allowDOH && data->set.doh) {
|
||||
addr = Curl_doh(conn, hostname, port, &respwait);
|
||||
}
|
||||
else {
|
||||
/* If Curl_getaddrinfo() returns NULL, 'respwait' might be set to a
|
||||
non-zero value indicating that we need to wait for the response to
|
||||
the resolve call */
|
||||
addr = Curl_getaddrinfo(conn,
|
||||
#ifdef DEBUGBUILD
|
||||
(data->set.str[STRING_DEVICE]
|
||||
&& !strcmp(data->set.str[STRING_DEVICE],
|
||||
"LocalHost"))?"localhost":
|
||||
(data->set.str[STRING_DEVICE]
|
||||
&& !strcmp(data->set.str[STRING_DEVICE],
|
||||
"LocalHost"))?"localhost":
|
||||
#endif
|
||||
hostname, port, &respwait);
|
||||
hostname, port, &respwait);
|
||||
}
|
||||
}
|
||||
if(!addr) {
|
||||
if(respwait) {
|
||||
@ -620,11 +642,11 @@ RETSIGTYPE alarmfunc(int sig)
|
||||
* CURLRESOLV_PENDING (1) = waiting for response, no pointer
|
||||
*/
|
||||
|
||||
int Curl_resolv_timeout(struct connectdata *conn,
|
||||
const char *hostname,
|
||||
int port,
|
||||
struct Curl_dns_entry **entry,
|
||||
time_t timeoutms)
|
||||
enum resolve_t Curl_resolv_timeout(struct connectdata *conn,
|
||||
const char *hostname,
|
||||
int port,
|
||||
struct Curl_dns_entry **entry,
|
||||
timediff_t timeoutms)
|
||||
{
|
||||
#ifdef USE_ALARM_TIMEOUT
|
||||
#ifdef HAVE_SIGACTION
|
||||
@ -640,7 +662,7 @@ int Curl_resolv_timeout(struct connectdata *conn,
|
||||
volatile unsigned int prev_alarm = 0;
|
||||
struct Curl_easy *data = conn->data;
|
||||
#endif /* USE_ALARM_TIMEOUT */
|
||||
int rc;
|
||||
enum resolve_t rc;
|
||||
|
||||
*entry = NULL;
|
||||
|
||||
@ -749,7 +771,7 @@ clean_up:
|
||||
conn->created) / 1000;
|
||||
|
||||
/* the alarm period is counted in even number of seconds */
|
||||
unsigned long alarm_set = prev_alarm - elapsed_secs;
|
||||
unsigned long alarm_set = (unsigned long)(prev_alarm - elapsed_secs);
|
||||
|
||||
if(!alarm_set ||
|
||||
((alarm_set >= 0x80000000) && (prev_alarm < 0x80000000)) ) {
|
||||
@ -1021,25 +1043,27 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
|
||||
CURLcode Curl_resolv_check(struct connectdata *conn,
|
||||
struct Curl_dns_entry **dns)
|
||||
{
|
||||
#if defined(CURL_DISABLE_DOH) && !defined(CURLRES_ASYNCH)
|
||||
(void)dns;
|
||||
#endif
|
||||
|
||||
if(conn->data->set.doh)
|
||||
return Curl_doh_is_resolved(conn, dns);
|
||||
return Curl_resolver_is_resolved(conn, dns);
|
||||
}
|
||||
|
||||
int Curl_resolv_getsock(struct connectdata *conn,
|
||||
curl_socket_t *socks,
|
||||
int numsocks)
|
||||
curl_socket_t *socks)
|
||||
{
|
||||
#ifdef CURLRES_ASYNCH
|
||||
if(conn->data->set.doh)
|
||||
/* nothing to wait for during DOH resolve, those handles have their own
|
||||
sockets */
|
||||
return GETSOCK_BLANK;
|
||||
return Curl_resolver_getsock(conn, socks, numsocks);
|
||||
return Curl_resolver_getsock(conn, socks);
|
||||
#else
|
||||
(void)conn;
|
||||
(void)socks;
|
||||
(void)numsocks;
|
||||
return GETSOCK_BLANK;
|
||||
#endif
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2020, 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
|
||||
@ -25,6 +25,7 @@
|
||||
#include "curl_setup.h"
|
||||
#include "hash.h"
|
||||
#include "curl_addrinfo.h"
|
||||
#include "timeval.h" /* for timediff_t */
|
||||
#include "asyn.h"
|
||||
|
||||
#ifdef HAVE_SETJMP_H
|
||||
@ -61,7 +62,6 @@ struct connectdata;
|
||||
* Returns a struct curl_hash pointer on success, NULL on failure.
|
||||
*/
|
||||
struct curl_hash *Curl_global_host_cache_init(void);
|
||||
void Curl_global_host_cache_dtor(void);
|
||||
|
||||
struct Curl_dns_entry {
|
||||
Curl_addrinfo *addr;
|
||||
@ -79,26 +79,29 @@ struct Curl_dns_entry {
|
||||
* use, or we'll leak memory!
|
||||
*/
|
||||
/* return codes */
|
||||
#define CURLRESOLV_TIMEDOUT -2
|
||||
#define CURLRESOLV_ERROR -1
|
||||
#define CURLRESOLV_RESOLVED 0
|
||||
#define CURLRESOLV_PENDING 1
|
||||
int Curl_resolv(struct connectdata *conn,
|
||||
const char *hostname,
|
||||
int port,
|
||||
bool allowDOH,
|
||||
struct Curl_dns_entry **dnsentry);
|
||||
int Curl_resolv_timeout(struct connectdata *conn, const char *hostname,
|
||||
int port, struct Curl_dns_entry **dnsentry,
|
||||
time_t timeoutms);
|
||||
enum resolve_t {
|
||||
CURLRESOLV_TIMEDOUT = -2,
|
||||
CURLRESOLV_ERROR = -1,
|
||||
CURLRESOLV_RESOLVED = 0,
|
||||
CURLRESOLV_PENDING = 1
|
||||
};
|
||||
enum resolve_t Curl_resolv(struct connectdata *conn,
|
||||
const char *hostname,
|
||||
int port,
|
||||
bool allowDOH,
|
||||
struct Curl_dns_entry **dnsentry);
|
||||
enum resolve_t Curl_resolv_timeout(struct connectdata *conn,
|
||||
const char *hostname, int port,
|
||||
struct Curl_dns_entry **dnsentry,
|
||||
timediff_t timeoutms);
|
||||
|
||||
#ifdef CURLRES_IPV6
|
||||
/*
|
||||
* Curl_ipv6works() returns TRUE if IPv6 seems to work.
|
||||
*/
|
||||
bool Curl_ipv6works(void);
|
||||
bool Curl_ipv6works(struct connectdata *conn);
|
||||
#else
|
||||
#define Curl_ipv6works() FALSE
|
||||
#define Curl_ipv6works(x) FALSE
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -124,9 +127,6 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
|
||||
void Curl_resolv_unlock(struct Curl_easy *data,
|
||||
struct Curl_dns_entry *dns);
|
||||
|
||||
/* for debugging purposes only: */
|
||||
void Curl_scan_cache_used(void *user, void *ptr);
|
||||
|
||||
/* init a new dns cache and return success */
|
||||
int Curl_mk_dnscache(struct curl_hash *hash);
|
||||
|
||||
@ -236,11 +236,6 @@ CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data,
|
||||
*/
|
||||
void Curl_hostcache_clean(struct Curl_easy *data, struct curl_hash *hash);
|
||||
|
||||
/*
|
||||
* Destroy the hostcache of this handle.
|
||||
*/
|
||||
void Curl_hostcache_destroy(struct Curl_easy *data);
|
||||
|
||||
/*
|
||||
* Populate the cache with specified entries from CURLOPT_RESOLVE.
|
||||
*/
|
||||
@ -249,7 +244,6 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data);
|
||||
CURLcode Curl_resolv_check(struct connectdata *conn,
|
||||
struct Curl_dns_entry **dns);
|
||||
int Curl_resolv_getsock(struct connectdata *conn,
|
||||
curl_socket_t *socks,
|
||||
int numsocks);
|
||||
curl_socket_t *socks);
|
||||
|
||||
#endif /* HEADER_CURL_HOSTIP_H */
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2020, 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
|
||||
@ -52,7 +52,6 @@
|
||||
#include "share.h"
|
||||
#include "strerror.h"
|
||||
#include "url.h"
|
||||
#include "inet_pton.h"
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
@ -128,28 +127,22 @@ Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
|
||||
#endif
|
||||
Curl_addrinfo *ai = NULL;
|
||||
struct hostent *h = NULL;
|
||||
struct in_addr in;
|
||||
struct hostent *buf = NULL;
|
||||
|
||||
if(Curl_inet_pton(AF_INET, hostname, &in) > 0)
|
||||
/* This is a dotted IP address 123.123.123.123-style */
|
||||
return Curl_ip2addr(AF_INET, &in, hostname, port);
|
||||
|
||||
#if defined(HAVE_GETADDRINFO_THREADSAFE)
|
||||
else {
|
||||
struct addrinfo hints;
|
||||
char sbuf[12];
|
||||
char *sbufptr = NULL;
|
||||
struct addrinfo hints;
|
||||
char sbuf[12];
|
||||
char *sbufptr = NULL;
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = PF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
if(port) {
|
||||
msnprintf(sbuf, sizeof(sbuf), "%d", port);
|
||||
sbufptr = sbuf;
|
||||
}
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = PF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
if(port) {
|
||||
msnprintf(sbuf, sizeof(sbuf), "%d", port);
|
||||
sbufptr = sbuf;
|
||||
}
|
||||
|
||||
(void)Curl_getaddrinfo_ex(hostname, sbufptr, &hints, &ai);
|
||||
(void)Curl_getaddrinfo_ex(hostname, sbufptr, &hints, &ai);
|
||||
|
||||
#elif defined(HAVE_GETHOSTBYNAME_R)
|
||||
/*
|
||||
@ -157,144 +150,141 @@ Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
|
||||
* Since there are three different versions of it, the following code is
|
||||
* somewhat #ifdef-ridden.
|
||||
*/
|
||||
else {
|
||||
int h_errnop;
|
||||
int h_errnop;
|
||||
|
||||
buf = calloc(1, CURL_HOSTENT_SIZE);
|
||||
if(!buf)
|
||||
return NULL; /* major failure */
|
||||
/*
|
||||
* The clearing of the buffer is a workaround for a gethostbyname_r bug in
|
||||
* qnx nto and it is also _required_ for some of these functions on some
|
||||
* platforms.
|
||||
*/
|
||||
buf = calloc(1, CURL_HOSTENT_SIZE);
|
||||
if(!buf)
|
||||
return NULL; /* major failure */
|
||||
/*
|
||||
* The clearing of the buffer is a workaround for a gethostbyname_r bug in
|
||||
* qnx nto and it is also _required_ for some of these functions on some
|
||||
* platforms.
|
||||
*/
|
||||
|
||||
#if defined(HAVE_GETHOSTBYNAME_R_5)
|
||||
/* Solaris, IRIX and more */
|
||||
h = gethostbyname_r(hostname,
|
||||
(struct hostent *)buf,
|
||||
(char *)buf + sizeof(struct hostent),
|
||||
CURL_HOSTENT_SIZE - sizeof(struct hostent),
|
||||
&h_errnop);
|
||||
/* Solaris, IRIX and more */
|
||||
h = gethostbyname_r(hostname,
|
||||
(struct hostent *)buf,
|
||||
(char *)buf + sizeof(struct hostent),
|
||||
CURL_HOSTENT_SIZE - sizeof(struct hostent),
|
||||
&h_errnop);
|
||||
|
||||
/* If the buffer is too small, it returns NULL and sets errno to
|
||||
* ERANGE. The errno is thread safe if this is compiled with
|
||||
* -D_REENTRANT as then the 'errno' variable is a macro defined to get
|
||||
* used properly for threads.
|
||||
*/
|
||||
/* If the buffer is too small, it returns NULL and sets errno to
|
||||
* ERANGE. The errno is thread safe if this is compiled with
|
||||
* -D_REENTRANT as then the 'errno' variable is a macro defined to get
|
||||
* used properly for threads.
|
||||
*/
|
||||
|
||||
if(h) {
|
||||
;
|
||||
}
|
||||
else
|
||||
#elif defined(HAVE_GETHOSTBYNAME_R_6)
|
||||
/* Linux */
|
||||
|
||||
(void)gethostbyname_r(hostname,
|
||||
(struct hostent *)buf,
|
||||
(char *)buf + sizeof(struct hostent),
|
||||
CURL_HOSTENT_SIZE - sizeof(struct hostent),
|
||||
&h, /* DIFFERENCE */
|
||||
&h_errnop);
|
||||
/* Redhat 8, using glibc 2.2.93 changed the behavior. Now all of a
|
||||
* sudden this function returns EAGAIN if the given buffer size is too
|
||||
* small. Previous versions are known to return ERANGE for the same
|
||||
* problem.
|
||||
*
|
||||
* This wouldn't be such a big problem if older versions wouldn't
|
||||
* sometimes return EAGAIN on a common failure case. Alas, we can't
|
||||
* assume that EAGAIN *or* ERANGE means ERANGE for any given version of
|
||||
* glibc.
|
||||
*
|
||||
* For now, we do that and thus we may call the function repeatedly and
|
||||
* fail for older glibc versions that return EAGAIN, until we run out of
|
||||
* buffer size (step_size grows beyond CURL_HOSTENT_SIZE).
|
||||
*
|
||||
* If anyone has a better fix, please tell us!
|
||||
*
|
||||
* -------------------------------------------------------------------
|
||||
*
|
||||
* On October 23rd 2003, Dan C dug up more details on the mysteries of
|
||||
* gethostbyname_r() in glibc:
|
||||
*
|
||||
* In glibc 2.2.5 the interface is different (this has also been
|
||||
* discovered in glibc 2.1.1-6 as shipped by Redhat 6). What I can't
|
||||
* explain, is that tests performed on glibc 2.2.4-34 and 2.2.4-32
|
||||
* (shipped/upgraded by Redhat 7.2) don't show this behavior!
|
||||
*
|
||||
* In this "buggy" version, the return code is -1 on error and 'errno'
|
||||
* is set to the ERANGE or EAGAIN code. Note that 'errno' is not a
|
||||
* thread-safe variable.
|
||||
*/
|
||||
|
||||
if(!h) /* failure */
|
||||
#elif defined(HAVE_GETHOSTBYNAME_R_3)
|
||||
/* AIX, Digital Unix/Tru64, HPUX 10, more? */
|
||||
|
||||
/* For AIX 4.3 or later, we don't use gethostbyname_r() at all, because of
|
||||
* the plain fact that it does not return unique full buffers on each
|
||||
* call, but instead several of the pointers in the hostent structs will
|
||||
* point to the same actual data! This have the unfortunate down-side that
|
||||
* our caching system breaks down horribly. Luckily for us though, AIX 4.3
|
||||
* and more recent versions have a "completely thread-safe"[*] libc where
|
||||
* all the data is stored in thread-specific memory areas making calls to
|
||||
* the plain old gethostbyname() work fine even for multi-threaded
|
||||
* programs.
|
||||
*
|
||||
* This AIX 4.3 or later detection is all made in the configure script.
|
||||
*
|
||||
* Troels Walsted Hansen helped us work this out on March 3rd, 2003.
|
||||
*
|
||||
* [*] = much later we've found out that it isn't at all "completely
|
||||
* thread-safe", but at least the gethostbyname() function is.
|
||||
*/
|
||||
|
||||
if(CURL_HOSTENT_SIZE >=
|
||||
(sizeof(struct hostent) + sizeof(struct hostent_data))) {
|
||||
|
||||
/* August 22nd, 2000: Albert Chin-A-Young brought an updated version
|
||||
* that should work! September 20: Richard Prescott worked on the buffer
|
||||
* size dilemma.
|
||||
*/
|
||||
|
||||
res = gethostbyname_r(hostname,
|
||||
(struct hostent *)buf,
|
||||
(struct hostent_data *)((char *)buf +
|
||||
sizeof(struct hostent)));
|
||||
h_errnop = SOCKERRNO; /* we don't deal with this, but set it anyway */
|
||||
}
|
||||
else
|
||||
res = -1; /* failure, too smallish buffer size */
|
||||
|
||||
if(!res) { /* success */
|
||||
|
||||
h = buf; /* result expected in h */
|
||||
|
||||
/* This is the worst kind of the different gethostbyname_r() interfaces.
|
||||
* Since we don't know how big buffer this particular lookup required,
|
||||
* we can't realloc down the huge alloc without doing closer analysis of
|
||||
* the returned data. Thus, we always use CURL_HOSTENT_SIZE for every
|
||||
* name lookup. Fixing this would require an extra malloc() and then
|
||||
* calling Curl_addrinfo_copy() that subsequent realloc()s down the new
|
||||
* memory area to the actually used amount.
|
||||
*/
|
||||
}
|
||||
else
|
||||
#endif /* HAVE_...BYNAME_R_5 || HAVE_...BYNAME_R_6 || HAVE_...BYNAME_R_3 */
|
||||
{
|
||||
h = NULL; /* set return code to NULL */
|
||||
free(buf);
|
||||
}
|
||||
#else /* HAVE_GETADDRINFO_THREADSAFE || HAVE_GETHOSTBYNAME_R */
|
||||
/*
|
||||
* Here is code for platforms that don't have a thread safe
|
||||
* getaddrinfo() nor gethostbyname_r() function or for which
|
||||
* gethostbyname() is the preferred one.
|
||||
*/
|
||||
else {
|
||||
h = gethostbyname((void *)hostname);
|
||||
#endif /* HAVE_GETADDRINFO_THREADSAFE || HAVE_GETHOSTBYNAME_R */
|
||||
if(h) {
|
||||
;
|
||||
}
|
||||
else
|
||||
#elif defined(HAVE_GETHOSTBYNAME_R_6)
|
||||
/* Linux */
|
||||
|
||||
(void)gethostbyname_r(hostname,
|
||||
(struct hostent *)buf,
|
||||
(char *)buf + sizeof(struct hostent),
|
||||
CURL_HOSTENT_SIZE - sizeof(struct hostent),
|
||||
&h, /* DIFFERENCE */
|
||||
&h_errnop);
|
||||
/* Redhat 8, using glibc 2.2.93 changed the behavior. Now all of a
|
||||
* sudden this function returns EAGAIN if the given buffer size is too
|
||||
* small. Previous versions are known to return ERANGE for the same
|
||||
* problem.
|
||||
*
|
||||
* This wouldn't be such a big problem if older versions wouldn't
|
||||
* sometimes return EAGAIN on a common failure case. Alas, we can't
|
||||
* assume that EAGAIN *or* ERANGE means ERANGE for any given version of
|
||||
* glibc.
|
||||
*
|
||||
* For now, we do that and thus we may call the function repeatedly and
|
||||
* fail for older glibc versions that return EAGAIN, until we run out of
|
||||
* buffer size (step_size grows beyond CURL_HOSTENT_SIZE).
|
||||
*
|
||||
* If anyone has a better fix, please tell us!
|
||||
*
|
||||
* -------------------------------------------------------------------
|
||||
*
|
||||
* On October 23rd 2003, Dan C dug up more details on the mysteries of
|
||||
* gethostbyname_r() in glibc:
|
||||
*
|
||||
* In glibc 2.2.5 the interface is different (this has also been
|
||||
* discovered in glibc 2.1.1-6 as shipped by Redhat 6). What I can't
|
||||
* explain, is that tests performed on glibc 2.2.4-34 and 2.2.4-32
|
||||
* (shipped/upgraded by Redhat 7.2) don't show this behavior!
|
||||
*
|
||||
* In this "buggy" version, the return code is -1 on error and 'errno'
|
||||
* is set to the ERANGE or EAGAIN code. Note that 'errno' is not a
|
||||
* thread-safe variable.
|
||||
*/
|
||||
|
||||
if(!h) /* failure */
|
||||
#elif defined(HAVE_GETHOSTBYNAME_R_3)
|
||||
/* AIX, Digital Unix/Tru64, HPUX 10, more? */
|
||||
|
||||
/* For AIX 4.3 or later, we don't use gethostbyname_r() at all, because of
|
||||
* the plain fact that it does not return unique full buffers on each
|
||||
* call, but instead several of the pointers in the hostent structs will
|
||||
* point to the same actual data! This have the unfortunate down-side that
|
||||
* our caching system breaks down horribly. Luckily for us though, AIX 4.3
|
||||
* and more recent versions have a "completely thread-safe"[*] libc where
|
||||
* all the data is stored in thread-specific memory areas making calls to
|
||||
* the plain old gethostbyname() work fine even for multi-threaded
|
||||
* programs.
|
||||
*
|
||||
* This AIX 4.3 or later detection is all made in the configure script.
|
||||
*
|
||||
* Troels Walsted Hansen helped us work this out on March 3rd, 2003.
|
||||
*
|
||||
* [*] = much later we've found out that it isn't at all "completely
|
||||
* thread-safe", but at least the gethostbyname() function is.
|
||||
*/
|
||||
|
||||
if(CURL_HOSTENT_SIZE >=
|
||||
(sizeof(struct hostent) + sizeof(struct hostent_data))) {
|
||||
|
||||
/* August 22nd, 2000: Albert Chin-A-Young brought an updated version
|
||||
* that should work! September 20: Richard Prescott worked on the buffer
|
||||
* size dilemma.
|
||||
*/
|
||||
|
||||
res = gethostbyname_r(hostname,
|
||||
(struct hostent *)buf,
|
||||
(struct hostent_data *)((char *)buf +
|
||||
sizeof(struct hostent)));
|
||||
h_errnop = SOCKERRNO; /* we don't deal with this, but set it anyway */
|
||||
}
|
||||
else
|
||||
res = -1; /* failure, too smallish buffer size */
|
||||
|
||||
if(!res) { /* success */
|
||||
|
||||
h = buf; /* result expected in h */
|
||||
|
||||
/* This is the worst kind of the different gethostbyname_r() interfaces.
|
||||
* Since we don't know how big buffer this particular lookup required,
|
||||
* we can't realloc down the huge alloc without doing closer analysis of
|
||||
* the returned data. Thus, we always use CURL_HOSTENT_SIZE for every
|
||||
* name lookup. Fixing this would require an extra malloc() and then
|
||||
* calling Curl_addrinfo_copy() that subsequent realloc()s down the new
|
||||
* memory area to the actually used amount.
|
||||
*/
|
||||
}
|
||||
else
|
||||
#endif /* HAVE_...BYNAME_R_5 || HAVE_...BYNAME_R_6 || HAVE_...BYNAME_R_3 */
|
||||
{
|
||||
h = NULL; /* set return code to NULL */
|
||||
free(buf);
|
||||
}
|
||||
#else /* HAVE_GETADDRINFO_THREADSAFE || HAVE_GETHOSTBYNAME_R */
|
||||
/*
|
||||
* Here is code for platforms that don't have a thread safe
|
||||
* getaddrinfo() nor gethostbyname_r() function or for which
|
||||
* gethostbyname() is the preferred one.
|
||||
*/
|
||||
h = gethostbyname((void *)hostname);
|
||||
#endif /* HAVE_GETADDRINFO_THREADSAFE || HAVE_GETHOSTBYNAME_R */
|
||||
|
||||
if(h) {
|
||||
ai = Curl_he2ai(h, port);
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2020, 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
|
||||
@ -62,13 +62,19 @@
|
||||
/*
|
||||
* Curl_ipv6works() returns TRUE if IPv6 seems to work.
|
||||
*/
|
||||
bool Curl_ipv6works(void)
|
||||
bool Curl_ipv6works(struct connectdata *conn)
|
||||
{
|
||||
/* 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 */
|
||||
static int ipv6_works = -1;
|
||||
if(-1 == ipv6_works) {
|
||||
if(conn) {
|
||||
/* 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 */
|
||||
DEBUGASSERT(conn);
|
||||
DEBUGASSERT(conn->data);
|
||||
DEBUGASSERT(conn->data->multi);
|
||||
return conn->data->multi->ipv6_works;
|
||||
}
|
||||
else {
|
||||
int ipv6_works = -1;
|
||||
/* probe to see if we have a working IPv6 stack */
|
||||
curl_socket_t s = socket(PF_INET6, SOCK_DGRAM, 0);
|
||||
if(s == CURL_SOCKET_BAD)
|
||||
@ -78,8 +84,8 @@ bool Curl_ipv6works(void)
|
||||
ipv6_works = 1;
|
||||
Curl_closesocket(NULL, s);
|
||||
}
|
||||
return (ipv6_works>0)?TRUE:FALSE;
|
||||
}
|
||||
return (ipv6_works>0)?TRUE:FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -89,7 +95,7 @@ bool Curl_ipv6works(void)
|
||||
bool Curl_ipvalid(struct connectdata *conn)
|
||||
{
|
||||
if(conn->ip_version == CURL_IPRESOLVE_V6)
|
||||
return Curl_ipv6works();
|
||||
return Curl_ipv6works(conn);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -159,13 +165,14 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
|
||||
break;
|
||||
}
|
||||
|
||||
if((pf != PF_INET) && !Curl_ipv6works())
|
||||
if((pf != PF_INET) && !Curl_ipv6works(conn))
|
||||
/* The stack seems to be a non-IPv6 one */
|
||||
pf = PF_INET;
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = pf;
|
||||
hints.ai_socktype = conn->socktype;
|
||||
hints.ai_socktype = (conn->transport == TRNSPRT_TCP) ?
|
||||
SOCK_STREAM : SOCK_DGRAM;
|
||||
|
||||
#ifndef USE_RESOLVE_ON_IPS
|
||||
/*
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2019, 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
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2020, 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
|
||||
@ -88,8 +88,7 @@
|
||||
*/
|
||||
|
||||
static int http_getsock_do(struct connectdata *conn,
|
||||
curl_socket_t *socks,
|
||||
int numsocks);
|
||||
curl_socket_t *socks);
|
||||
static int http_should_fail(struct connectdata *conn);
|
||||
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
@ -99,8 +98,7 @@ static CURLcode add_haproxy_protocol_header(struct connectdata *conn);
|
||||
#ifdef USE_SSL
|
||||
static CURLcode https_connecting(struct connectdata *conn, bool *done);
|
||||
static int https_getsock(struct connectdata *conn,
|
||||
curl_socket_t *socks,
|
||||
int numsocks);
|
||||
curl_socket_t *socks);
|
||||
#else
|
||||
#define https_connecting(x,y) CURLE_COULDNT_CONNECT
|
||||
#endif
|
||||
@ -171,10 +169,22 @@ static CURLcode http_setup_conn(struct connectdata *conn)
|
||||
Curl_mime_initpart(&http->form, conn->data);
|
||||
data->req.protop = http;
|
||||
|
||||
if(!CONN_INUSE(conn))
|
||||
/* if not already multi-using, setup connection details */
|
||||
Curl_http2_setup_conn(conn);
|
||||
Curl_http2_setup_req(data);
|
||||
if(data->set.httpversion == CURL_HTTP_VERSION_3) {
|
||||
if(conn->handler->flags & PROTOPT_SSL)
|
||||
/* Only go HTTP/3 directly on HTTPS URLs. It needs a UDP socket and does
|
||||
the QUIC dance. */
|
||||
conn->transport = TRNSPRT_QUIC;
|
||||
else {
|
||||
failf(data, "HTTP/3 requested for non-HTTPS URL");
|
||||
return CURLE_URL_MALFORMAT;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(!CONN_INUSE(conn))
|
||||
/* if not already multi-using, setup connection details */
|
||||
Curl_http2_setup_conn(conn);
|
||||
Curl_http2_setup_req(data);
|
||||
}
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
@ -334,7 +344,7 @@ static CURLcode http_output_bearer(struct connectdata *conn)
|
||||
userp = &conn->allocptr.userpwd;
|
||||
free(*userp);
|
||||
*userp = aprintf("Authorization: Bearer %s\r\n",
|
||||
conn->oauth_bearer);
|
||||
conn->data->set.str[STRING_BEARER]);
|
||||
|
||||
if(!*userp) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
@ -383,7 +393,7 @@ static bool pickoneauth(struct auth *pick, unsigned long mask)
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_http_perhapsrewind()
|
||||
* http_perhapsrewind()
|
||||
*
|
||||
* If we are doing POST or PUT {
|
||||
* If we have more data to send {
|
||||
@ -440,9 +450,6 @@ static CURLcode http_perhapsrewind(struct connectdata *conn)
|
||||
/* figure out how much data we are expected to send */
|
||||
switch(data->set.httpreq) {
|
||||
case HTTPREQ_POST:
|
||||
if(data->state.infilesize != -1)
|
||||
expectsend = data->state.infilesize;
|
||||
break;
|
||||
case HTTPREQ_PUT:
|
||||
if(data->state.infilesize != -1)
|
||||
expectsend = data->state.infilesize;
|
||||
@ -548,7 +555,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
|
||||
CURLcode result = CURLE_OK;
|
||||
unsigned long authmask = ~0ul;
|
||||
|
||||
if(!conn->oauth_bearer)
|
||||
if(!data->set.str[STRING_BEARER])
|
||||
authmask &= (unsigned long)~CURLAUTH_BEARER;
|
||||
|
||||
if(100 <= data->req.httpcode && 199 >= data->req.httpcode)
|
||||
@ -558,7 +565,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
|
||||
if(data->state.authproblem)
|
||||
return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK;
|
||||
|
||||
if((conn->bits.user_passwd || conn->oauth_bearer) &&
|
||||
if((conn->bits.user_passwd || data->set.str[STRING_BEARER]) &&
|
||||
((data->req.httpcode == 401) ||
|
||||
(conn->bits.authneg && data->req.httpcode < 300))) {
|
||||
pickhost = pickoneauth(&data->state.authhost, authmask);
|
||||
@ -634,9 +641,7 @@ output_auth_headers(struct connectdata *conn,
|
||||
{
|
||||
const char *auth = NULL;
|
||||
CURLcode result = CURLE_OK;
|
||||
#if !defined(CURL_DISABLE_VERBOSE_STRINGS) || defined(USE_SPNEGO)
|
||||
struct Curl_easy *data = conn->data;
|
||||
#endif
|
||||
|
||||
#ifdef CURL_DISABLE_CRYPTO_AUTH
|
||||
(void)request;
|
||||
@ -644,7 +649,7 @@ output_auth_headers(struct connectdata *conn,
|
||||
#endif
|
||||
|
||||
#ifdef USE_SPNEGO
|
||||
if((authstatus->picked == CURLAUTH_NEGOTIATE)) {
|
||||
if(authstatus->picked == CURLAUTH_NEGOTIATE) {
|
||||
auth = "Negotiate";
|
||||
result = Curl_output_negotiate(conn, proxy);
|
||||
if(result)
|
||||
@ -700,7 +705,7 @@ output_auth_headers(struct connectdata *conn,
|
||||
}
|
||||
if(authstatus->picked == CURLAUTH_BEARER) {
|
||||
/* Bearer */
|
||||
if((!proxy && conn->oauth_bearer &&
|
||||
if((!proxy && data->set.str[STRING_BEARER] &&
|
||||
!Curl_checkheaders(conn, "Authorization:"))) {
|
||||
auth = "Bearer";
|
||||
result = http_output_bearer(conn);
|
||||
@ -758,7 +763,7 @@ Curl_http_output_auth(struct connectdata *conn,
|
||||
authproxy = &data->state.authproxy;
|
||||
|
||||
if((conn->bits.httpproxy && conn->bits.proxy_user_passwd) ||
|
||||
conn->bits.user_passwd || conn->oauth_bearer)
|
||||
conn->bits.user_passwd || data->set.str[STRING_BEARER])
|
||||
/* continue please */;
|
||||
else {
|
||||
authhost->done = TRUE;
|
||||
@ -1136,10 +1141,14 @@ Curl_send_buffer *Curl_add_buffer_init(void)
|
||||
*/
|
||||
void Curl_add_buffer_free(Curl_send_buffer **inp)
|
||||
{
|
||||
Curl_send_buffer *in = *inp;
|
||||
if(in) /* deal with NULL input */
|
||||
Curl_send_buffer *in;
|
||||
if(!inp)
|
||||
return;
|
||||
in = *inp;
|
||||
if(in) { /* deal with NULL input */
|
||||
free(in->buffer);
|
||||
free(in);
|
||||
free(in);
|
||||
}
|
||||
*inp = NULL;
|
||||
}
|
||||
|
||||
@ -1497,11 +1506,9 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
|
||||
interface and then we're always _sending_ a request and thus we wait for
|
||||
the single socket to become writable only */
|
||||
static int http_getsock_do(struct connectdata *conn,
|
||||
curl_socket_t *socks,
|
||||
int numsocks)
|
||||
curl_socket_t *socks)
|
||||
{
|
||||
/* write mode */
|
||||
(void)numsocks; /* unused, we trust it to be at least 1 */
|
||||
socks[0] = conn->sock[FIRSTSOCKET];
|
||||
return GETSOCK_WRITESOCK(0);
|
||||
}
|
||||
@ -1555,6 +1562,13 @@ static CURLcode https_connecting(struct connectdata *conn, bool *done)
|
||||
CURLcode result;
|
||||
DEBUGASSERT((conn) && (conn->handler->flags & PROTOPT_SSL));
|
||||
|
||||
#ifdef ENABLE_QUIC
|
||||
if(conn->transport == TRNSPRT_QUIC) {
|
||||
*done = TRUE;
|
||||
return CURLE_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* perform SSL initialization for this socket */
|
||||
result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, done);
|
||||
if(result)
|
||||
@ -1564,11 +1578,10 @@ static CURLcode https_connecting(struct connectdata *conn, bool *done)
|
||||
}
|
||||
|
||||
static int https_getsock(struct connectdata *conn,
|
||||
curl_socket_t *socks,
|
||||
int numsocks)
|
||||
curl_socket_t *socks)
|
||||
{
|
||||
if(conn->handler->flags & PROTOPT_SSL)
|
||||
return Curl_ssl_getsock(conn, socks, numsocks);
|
||||
return Curl_ssl_getsock(conn, socks);
|
||||
return GETSOCK_BLANK;
|
||||
}
|
||||
#endif /* USE_SSL */
|
||||
@ -1602,7 +1615,8 @@ CURLcode Curl_http_done(struct connectdata *conn,
|
||||
Curl_add_buffer_free(&http->send_buffer);
|
||||
}
|
||||
|
||||
Curl_http2_done(conn, premature);
|
||||
Curl_http2_done(data, premature);
|
||||
Curl_quic_done(data, premature);
|
||||
|
||||
Curl_mime_cleanpart(&http->form);
|
||||
|
||||
@ -1650,6 +1664,12 @@ static bool use_http_1_1plus(const struct Curl_easy *data,
|
||||
static const char *get_http_string(const struct Curl_easy *data,
|
||||
const struct connectdata *conn)
|
||||
{
|
||||
#ifdef ENABLE_QUIC
|
||||
if((data->set.httpversion == CURL_HTTP_VERSION_3) ||
|
||||
(conn->httpversion == 30))
|
||||
return "3";
|
||||
#endif
|
||||
|
||||
#ifdef USE_NGHTTP2
|
||||
if(conn->proto.httpc.h2)
|
||||
return "2";
|
||||
@ -1669,8 +1689,8 @@ static CURLcode expect100(struct Curl_easy *data,
|
||||
CURLcode result = CURLE_OK;
|
||||
data->state.expect100header = FALSE; /* default to false unless it is set
|
||||
to TRUE below */
|
||||
if(use_http_1_1plus(data, conn) &&
|
||||
(conn->httpversion != 20)) {
|
||||
if(!data->state.disableexpect && use_http_1_1plus(data, conn) &&
|
||||
(conn->httpversion < 20)) {
|
||||
/* if not doing HTTP 1.0 or version 2, or disabled explicitly, we add an
|
||||
Expect: 100-continue to the headers which actually speeds up post
|
||||
operations (as there is one packet coming back from the web server) */
|
||||
@ -1700,7 +1720,7 @@ enum proxy_use {
|
||||
will return an error code if one of the headers is
|
||||
not formatted correctly */
|
||||
CURLcode Curl_http_compile_trailers(struct curl_slist *trailers,
|
||||
Curl_send_buffer *buffer,
|
||||
Curl_send_buffer **buffer,
|
||||
struct Curl_easy *handle)
|
||||
{
|
||||
char *ptr = NULL;
|
||||
@ -1726,7 +1746,7 @@ CURLcode Curl_http_compile_trailers(struct curl_slist *trailers,
|
||||
/* only add correctly formatted trailers */
|
||||
ptr = strchr(trailers->data, ':');
|
||||
if(ptr && *(ptr + 1) == ' ') {
|
||||
result = Curl_add_bufferf(&buffer, "%s%s", trailers->data,
|
||||
result = Curl_add_bufferf(buffer, "%s%s", trailers->data,
|
||||
endofline_native);
|
||||
if(result)
|
||||
return result;
|
||||
@ -1735,7 +1755,7 @@ CURLcode Curl_http_compile_trailers(struct curl_slist *trailers,
|
||||
infof(handle, "Malformatted trailing header ! Skipping trailer.");
|
||||
trailers = trailers->next;
|
||||
}
|
||||
result = Curl_add_buffer(&buffer, endofline_network,
|
||||
result = Curl_add_buffer(buffer, endofline_network,
|
||||
strlen(endofline_network));
|
||||
return result;
|
||||
}
|
||||
@ -1851,7 +1871,7 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
|
||||
Connection: */
|
||||
checkprefix("Connection:", compare))
|
||||
;
|
||||
else if((conn->httpversion == 20) &&
|
||||
else if((conn->httpversion >= 20) &&
|
||||
checkprefix("Transfer-Encoding:", compare))
|
||||
/* HTTP/2 doesn't support chunked requests */
|
||||
;
|
||||
@ -1881,9 +1901,10 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
|
||||
}
|
||||
|
||||
#ifndef CURL_DISABLE_PARSEDATE
|
||||
CURLcode Curl_add_timecondition(struct Curl_easy *data,
|
||||
CURLcode Curl_add_timecondition(const struct connectdata *conn,
|
||||
Curl_send_buffer *req_buffer)
|
||||
{
|
||||
struct Curl_easy *data = conn->data;
|
||||
const struct tm *tm;
|
||||
struct tm keeptime;
|
||||
CURLcode result;
|
||||
@ -1916,6 +1937,11 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data,
|
||||
break;
|
||||
}
|
||||
|
||||
if(Curl_checkheaders(conn, condp)) {
|
||||
/* A custom header was specified; it will be sent instead. */
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
/* The If-Modified-Since header family should have their times set in
|
||||
* GMT as RFC2616 defines: "All HTTP date/time stamps MUST be
|
||||
* represented in Greenwich Mean Time (GMT), without exception. For the
|
||||
@ -1941,10 +1967,10 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data,
|
||||
}
|
||||
#else
|
||||
/* disabled */
|
||||
CURLcode Curl_add_timecondition(struct Curl_easy *data,
|
||||
CURLcode Curl_add_timecondition(const struct connectdata *conn,
|
||||
Curl_send_buffer *req_buffer)
|
||||
{
|
||||
(void)data;
|
||||
(void)conn;
|
||||
(void)req_buffer;
|
||||
return CURLE_OK;
|
||||
}
|
||||
@ -1976,55 +2002,57 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
const char *httpstring;
|
||||
Curl_send_buffer *req_buffer;
|
||||
curl_off_t postsize = 0; /* curl_off_t to handle large file sizes */
|
||||
char *altused = NULL;
|
||||
|
||||
/* Always consider the DO phase done after this function call, even if there
|
||||
may be parts of the request that is not yet sent, since we can deal with
|
||||
the rest of the request in the PERFORM phase. */
|
||||
*done = TRUE;
|
||||
|
||||
if(conn->httpversion < 20) { /* unless the connection is re-used and already
|
||||
http2 */
|
||||
switch(conn->negnpn) {
|
||||
case CURL_HTTP_VERSION_2:
|
||||
conn->httpversion = 20; /* we know we're on HTTP/2 now */
|
||||
|
||||
result = Curl_http2_switched(conn, NULL, 0);
|
||||
if(result)
|
||||
return result;
|
||||
break;
|
||||
case CURL_HTTP_VERSION_1_1:
|
||||
/* continue with HTTP/1.1 when explicitly requested */
|
||||
break;
|
||||
default:
|
||||
/* Check if user wants to use HTTP/2 with clear TCP*/
|
||||
#ifdef USE_NGHTTP2
|
||||
if(conn->data->set.httpversion ==
|
||||
CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) {
|
||||
if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
|
||||
/* We don't support HTTP/2 proxies yet. Also it's debatable whether
|
||||
or not this setting should apply to HTTP/2 proxies. */
|
||||
infof(data, "Ignoring HTTP/2 prior knowledge due to proxy\n");
|
||||
break;
|
||||
}
|
||||
|
||||
DEBUGF(infof(data, "HTTP/2 over clean TCP\n"));
|
||||
conn->httpversion = 20;
|
||||
if(conn->transport != TRNSPRT_QUIC) {
|
||||
if(conn->httpversion < 20) { /* unless the connection is re-used and
|
||||
already http2 */
|
||||
switch(conn->negnpn) {
|
||||
case CURL_HTTP_VERSION_2:
|
||||
conn->httpversion = 20; /* we know we're on HTTP/2 now */
|
||||
|
||||
result = Curl_http2_switched(conn, NULL, 0);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
break;
|
||||
case CURL_HTTP_VERSION_1_1:
|
||||
/* continue with HTTP/1.1 when explicitly requested */
|
||||
break;
|
||||
default:
|
||||
/* Check if user wants to use HTTP/2 with clear TCP*/
|
||||
#ifdef USE_NGHTTP2
|
||||
if(conn->data->set.httpversion ==
|
||||
CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) {
|
||||
if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
|
||||
/* We don't support HTTP/2 proxies yet. Also it's debatable
|
||||
whether or not this setting should apply to HTTP/2 proxies. */
|
||||
infof(data, "Ignoring HTTP/2 prior knowledge due to proxy\n");
|
||||
break;
|
||||
}
|
||||
|
||||
DEBUGF(infof(data, "HTTP/2 over clean TCP\n"));
|
||||
conn->httpversion = 20;
|
||||
|
||||
result = Curl_http2_switched(conn, NULL, 0);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* prepare for a http2 request */
|
||||
result = Curl_http2_setup(conn);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* prepare for a http2 request */
|
||||
result = Curl_http2_setup(conn);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
http = data->req.protop;
|
||||
DEBUGASSERT(http);
|
||||
|
||||
@ -2220,14 +2248,16 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
else {
|
||||
if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
|
||||
(((httpreq == HTTPREQ_POST_MIME || httpreq == HTTPREQ_POST_FORM) &&
|
||||
http->postsize < 0) ||
|
||||
(data->set.upload && data->state.infilesize == -1))) {
|
||||
http->postsize < 0) ||
|
||||
((data->set.upload || httpreq == HTTPREQ_POST) &&
|
||||
data->state.infilesize == -1))) {
|
||||
if(conn->bits.authneg)
|
||||
/* don't enable chunked during auth neg */
|
||||
;
|
||||
else if(use_http_1_1plus(data, conn)) {
|
||||
/* HTTP, upload, unknown file size and not HTTP 1.0 */
|
||||
data->req.upload_chunky = TRUE;
|
||||
if(conn->httpversion < 20)
|
||||
/* HTTP, upload, unknown file size and not HTTP 1.0 */
|
||||
data->req.upload_chunky = TRUE;
|
||||
}
|
||||
else {
|
||||
failf(data, "Chunky upload is not supported by HTTP 1.0");
|
||||
@ -2328,7 +2358,6 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
|
||||
/* and no fragment part */
|
||||
CURLUcode uc;
|
||||
char *url;
|
||||
CURLU *h = curl_url_dup(data->state.uh);
|
||||
if(!h)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
@ -2359,19 +2388,15 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
/* now extract the new version of the URL */
|
||||
uc = curl_url_get(h, CURLUPART_URL, &url, 0);
|
||||
/* Extract the URL to use in the request. Store in STRING_TEMP_URL for
|
||||
clean-up reasons if the function returns before the free() further
|
||||
down. */
|
||||
uc = curl_url_get(h, CURLUPART_URL, &data->set.str[STRING_TEMP_URL], 0);
|
||||
if(uc) {
|
||||
curl_url_cleanup(h);
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if(data->change.url_alloc)
|
||||
free(data->change.url);
|
||||
|
||||
data->change.url = url;
|
||||
data->change.url_alloc = TRUE;
|
||||
|
||||
curl_url_cleanup(h);
|
||||
|
||||
if(strcasecompare("ftp", data->state.up.scheme)) {
|
||||
@ -2550,12 +2575,16 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
query = NULL;
|
||||
}
|
||||
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
/* url */
|
||||
if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
|
||||
char *url = data->change.url;
|
||||
char *url = data->set.str[STRING_TEMP_URL];
|
||||
result = Curl_add_buffer(&req_buffer, url, strlen(url));
|
||||
Curl_safefree(data->set.str[STRING_TEMP_URL]);
|
||||
}
|
||||
else if(paste_ftp_userpwd)
|
||||
else
|
||||
#endif
|
||||
if(paste_ftp_userpwd)
|
||||
result = Curl_add_bufferf(&req_buffer, "ftp://%s:%s@%s",
|
||||
conn->user, conn->passwd,
|
||||
path + sizeof("ftp://") - 1);
|
||||
@ -2569,6 +2598,14 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
#ifdef USE_ALTSVC
|
||||
if(conn->bits.altused && !Curl_checkheaders(conn, "Alt-Used")) {
|
||||
altused = aprintf("Alt-Used: %s:%d\r\n",
|
||||
conn->conn_to_host.name, conn->conn_to_port);
|
||||
if(!altused)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
#endif
|
||||
result =
|
||||
Curl_add_bufferf(&req_buffer,
|
||||
"%s" /* ftp typecode (;type=x) */
|
||||
@ -2583,7 +2620,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
"%s" /* accept-encoding */
|
||||
"%s" /* referer */
|
||||
"%s" /* Proxy-Connection */
|
||||
"%s",/* transfer-encoding */
|
||||
"%s" /* transfer-encoding */
|
||||
"%s",/* Alt-Used */
|
||||
|
||||
ftp_typecode,
|
||||
httpstring,
|
||||
@ -2609,13 +2647,15 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
!conn->bits.tunnel_proxy &&
|
||||
!Curl_checkProxyheaders(conn, "Proxy-Connection"))?
|
||||
"Proxy-Connection: Keep-Alive\r\n":"",
|
||||
te
|
||||
te,
|
||||
altused ? altused : ""
|
||||
);
|
||||
|
||||
/* clear userpwd and proxyuserpwd to avoid re-using old credentials
|
||||
* from re-used connections */
|
||||
Curl_safefree(conn->allocptr.userpwd);
|
||||
Curl_safefree(conn->allocptr.proxyuserpwd);
|
||||
free(altused);
|
||||
|
||||
if(result)
|
||||
return result;
|
||||
@ -2635,7 +2675,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
struct Cookie *co = NULL; /* no cookies from start */
|
||||
int count = 0;
|
||||
|
||||
if(data->cookies) {
|
||||
if(data->cookies && data->state.cookie_engine) {
|
||||
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
|
||||
co = Curl_cookie_getlist(data->cookies,
|
||||
conn->allocptr.cookiehost?
|
||||
@ -2683,7 +2723,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
}
|
||||
#endif
|
||||
|
||||
result = Curl_add_timecondition(data, req_buffer);
|
||||
result = Curl_add_timecondition(conn, req_buffer);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
@ -3000,11 +3040,12 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
|
||||
failf(data, "Failed sending HTTP request");
|
||||
else
|
||||
/* HTTP GET/HEAD download: */
|
||||
Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
|
||||
http->postdata?FIRSTSOCKET:-1);
|
||||
Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1);
|
||||
}
|
||||
if(result)
|
||||
return result;
|
||||
if(!postsize)
|
||||
data->req.upload_done = TRUE;
|
||||
|
||||
if(data->req.writebytecount) {
|
||||
/* if a request-body has been sent off, we make sure this progress is noted
|
||||
@ -3147,6 +3188,9 @@ static CURLcode header_append(struct Curl_easy *data,
|
||||
struct SingleRequest *k,
|
||||
size_t length)
|
||||
{
|
||||
/* length is at most the size of a full read buffer, for which the upper
|
||||
bound is CURL_MAX_READ_SIZE. There is thus no chance of overflow in this
|
||||
calculation. */
|
||||
size_t newsize = k->hbuflen + length;
|
||||
if(newsize > CURL_MAX_HTTP_HEADER) {
|
||||
/* The reason to have a max limit for this is to avoid the risk of a bad
|
||||
@ -3501,7 +3545,16 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
||||
*/
|
||||
Curl_expire_done(data, EXPIRE_100_TIMEOUT);
|
||||
if(!k->upload_done) {
|
||||
if(data->set.http_keep_sending_on_error) {
|
||||
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\n");
|
||||
data->state.disableexpect = TRUE;
|
||||
DEBUGASSERT(!data->req.newurl);
|
||||
data->req.newurl = strdup(conn->data->change.url);
|
||||
Curl_done_sending(conn, k);
|
||||
}
|
||||
else if(data->set.http_keep_sending_on_error) {
|
||||
infof(data, "HTTP error before end of send, keep sending\n");
|
||||
if(k->exp100 > EXP100_SEND_DATA) {
|
||||
k->exp100 = EXP100_SEND_DATA;
|
||||
@ -3511,8 +3564,10 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
||||
else {
|
||||
infof(data, "HTTP error before end of send, stop sending\n");
|
||||
streamclose(conn, "Stop sending data before everything sent");
|
||||
result = Curl_done_sending(conn, k);
|
||||
if(result)
|
||||
return result;
|
||||
k->upload_done = TRUE;
|
||||
k->keepon &= ~KEEP_SEND; /* don't send */
|
||||
if(data->state.expect100header)
|
||||
k->exp100 = EXP100_FAILED;
|
||||
}
|
||||
@ -3649,6 +3704,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
||||
* guarantees on future behaviors since it isn't within the protocol.
|
||||
*/
|
||||
char separator;
|
||||
char twoorthree[2];
|
||||
nc = sscanf(HEADER1,
|
||||
" HTTP/%1d.%1d%c%3d",
|
||||
&httpversion_major,
|
||||
@ -3656,8 +3712,8 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
||||
&separator,
|
||||
&k->httpcode);
|
||||
|
||||
if(nc == 1 && httpversion_major == 2 &&
|
||||
1 == sscanf(HEADER1, " HTTP/2 %d", &k->httpcode)) {
|
||||
if(nc == 1 && httpversion_major >= 2 &&
|
||||
2 == sscanf(HEADER1, " HTTP/%1[23] %d", twoorthree, &k->httpcode)) {
|
||||
conn->httpversion = 0;
|
||||
nc = 4;
|
||||
separator = ' ';
|
||||
@ -3695,7 +3751,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
||||
}
|
||||
}
|
||||
else {
|
||||
failf(data, "Unsupported HTTP version in response\n");
|
||||
failf(data, "Unsupported HTTP version in response");
|
||||
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||
}
|
||||
}
|
||||
@ -3769,6 +3825,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
||||
"HTTP 1.1 or later with persistent connection\n"));
|
||||
}
|
||||
|
||||
k->http_bodyless = k->httpcode >= 100 && k->httpcode < 200;
|
||||
switch(k->httpcode) {
|
||||
case 304:
|
||||
/* (quote from RFC2616, section 10.3.5): The 304 response
|
||||
@ -3786,10 +3843,9 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
||||
* empty line after the header fields. */
|
||||
k->size = 0;
|
||||
k->maxdownload = 0;
|
||||
k->ignorecl = TRUE; /* ignore Content-Length headers */
|
||||
k->http_bodyless = TRUE;
|
||||
break;
|
||||
default:
|
||||
/* nothing */
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -3805,8 +3861,8 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
||||
return result;
|
||||
|
||||
/* Check for Content-Length: header lines to get size */
|
||||
if(!k->ignorecl && !data->set.ignorecl &&
|
||||
checkprefix("Content-Length:", k->p)) {
|
||||
if(!k->http_bodyless &&
|
||||
!data->set.ignorecl && checkprefix("Content-Length:", k->p)) {
|
||||
curl_off_t contentlength;
|
||||
CURLofft offt = curlx_strtoofft(k->p + 15, NULL, 10, &contentlength);
|
||||
|
||||
@ -3895,7 +3951,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
||||
*/
|
||||
streamclose(conn, "Connection: close used");
|
||||
}
|
||||
else if(checkprefix("Transfer-Encoding:", k->p)) {
|
||||
else if(!k->http_bodyless && checkprefix("Transfer-Encoding:", k->p)) {
|
||||
/* One or more encodings. We check for chunked and/or a compression
|
||||
algorithm. */
|
||||
/*
|
||||
@ -3911,7 +3967,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
else if(checkprefix("Content-Encoding:", k->p) &&
|
||||
else if(!k->http_bodyless && checkprefix("Content-Encoding:", k->p) &&
|
||||
data->set.str[STRING_ENCODING]) {
|
||||
/*
|
||||
* Process Content-Encoding. Look for the values: identity,
|
||||
@ -3924,7 +3980,20 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
else if(checkprefix("Content-Range:", k->p)) {
|
||||
else if(checkprefix("Retry-After:", k->p)) {
|
||||
/* Retry-After = HTTP-date / delay-seconds */
|
||||
curl_off_t retry_after = 0; /* zero for unknown or "now" */
|
||||
time_t date = Curl_getdate_capped(&k->p[12]);
|
||||
if(-1 == date) {
|
||||
/* not a date, try it as a decimal number */
|
||||
(void)curlx_strtoofft(&k->p[12], NULL, 10, &retry_after);
|
||||
}
|
||||
else
|
||||
/* convert date to number of seconds into the future */
|
||||
retry_after = date - time(NULL);
|
||||
data->info.retry_after = retry_after; /* store it */
|
||||
}
|
||||
else if(!k->http_bodyless && checkprefix("Content-Range:", k->p)) {
|
||||
/* Content-Range: bytes [num]-
|
||||
Content-Range: bytes: [num]-
|
||||
Content-Range: [num]-
|
||||
@ -3954,7 +4023,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
||||
data->state.resume_from = 0; /* get everything */
|
||||
}
|
||||
#if !defined(CURL_DISABLE_COOKIES)
|
||||
else if(data->cookies &&
|
||||
else if(data->cookies && data->state.cookie_engine &&
|
||||
checkprefix("Set-Cookie:", k->p)) {
|
||||
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
|
||||
CURL_LOCK_ACCESS_SINGLE);
|
||||
@ -3970,11 +4039,9 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
||||
Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
|
||||
}
|
||||
#endif
|
||||
else if(checkprefix("Last-Modified:", k->p) &&
|
||||
else if(!k->http_bodyless && checkprefix("Last-Modified:", k->p) &&
|
||||
(data->set.timecondition || data->set.get_filetime) ) {
|
||||
time_t secs = time(NULL);
|
||||
k->timeofdoc = curl_getdate(k->p + strlen("Last-Modified:"),
|
||||
&secs);
|
||||
k->timeofdoc = Curl_getdate_capped(k->p + strlen("Last-Modified:"));
|
||||
if(data->set.get_filetime)
|
||||
data->info.filetime = k->timeofdoc;
|
||||
}
|
||||
@ -3995,7 +4062,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
#ifdef USE_SPNEGO
|
||||
#ifdef USE_SPNEGO
|
||||
else if(checkprefix("Persistent-Auth", k->p)) {
|
||||
struct negotiatedata *negdata = &conn->negotiate;
|
||||
struct auth *authp = &data->state.authhost;
|
||||
@ -4003,14 +4070,15 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
||||
char *persistentauth = Curl_copy_header_value(k->p);
|
||||
if(!persistentauth)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
negdata->noauthpersist = checkprefix("false", persistentauth);
|
||||
negdata->noauthpersist = checkprefix("false", persistentauth)?
|
||||
TRUE:FALSE;
|
||||
negdata->havenoauthpersist = TRUE;
|
||||
infof(data, "Negotiate: noauthpersist -> %d, header part: %s",
|
||||
negdata->noauthpersist, persistentauth);
|
||||
free(persistentauth);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
else if((k->httpcode >= 300 && k->httpcode < 400) &&
|
||||
checkprefix("Location:", k->p) &&
|
||||
!data->req.location) {
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2020, 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
|
||||
@ -69,32 +69,24 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer **inp,
|
||||
size_t included_body_bytes,
|
||||
int socketindex);
|
||||
|
||||
CURLcode Curl_add_timecondition(struct Curl_easy *data,
|
||||
CURLcode Curl_add_timecondition(const struct connectdata *conn,
|
||||
Curl_send_buffer *buf);
|
||||
CURLcode Curl_add_custom_headers(struct connectdata *conn,
|
||||
bool is_connect,
|
||||
Curl_send_buffer *req_buffer);
|
||||
CURLcode Curl_http_compile_trailers(struct curl_slist *trailers,
|
||||
Curl_send_buffer *buffer,
|
||||
Curl_send_buffer **buffer,
|
||||
struct Curl_easy *handle);
|
||||
|
||||
/* protocol-specific functions set up to be called by the main engine */
|
||||
CURLcode Curl_http(struct connectdata *conn, bool *done);
|
||||
CURLcode Curl_http_done(struct connectdata *, CURLcode, bool premature);
|
||||
CURLcode Curl_http_connect(struct connectdata *conn, bool *done);
|
||||
CURLcode Curl_http_setup_conn(struct connectdata *conn);
|
||||
|
||||
/* The following functions are defined in http_chunks.c */
|
||||
void Curl_httpchunk_init(struct connectdata *conn);
|
||||
CHUNKcode Curl_httpchunk_read(struct connectdata *conn, char *datap,
|
||||
ssize_t length, ssize_t *wrote);
|
||||
|
||||
/* These functions are in http.c */
|
||||
void Curl_http_auth_stage(struct Curl_easy *data, int stage);
|
||||
CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
|
||||
const char *auth);
|
||||
CURLcode Curl_http_auth_act(struct connectdata *conn);
|
||||
CURLcode Curl_http_perhapsrewind(struct connectdata *conn);
|
||||
|
||||
/* If only the PICKNONE bit is set, there has been a round-trip and we
|
||||
selected to use no auth at all. Ie, we actively select no auth, as opposed
|
||||
@ -124,11 +116,15 @@ CURLcode Curl_http_perhapsrewind(struct connectdata *conn);
|
||||
*
|
||||
*/
|
||||
#ifndef EXPECT_100_THRESHOLD
|
||||
#define EXPECT_100_THRESHOLD 1024
|
||||
#define EXPECT_100_THRESHOLD (1024*1024)
|
||||
#endif
|
||||
|
||||
#endif /* CURL_DISABLE_HTTP */
|
||||
|
||||
#ifdef USE_NGHTTP3
|
||||
struct h3out; /* see ngtcp2 */
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* HTTP unique setup
|
||||
***************************************************************************/
|
||||
@ -175,20 +171,40 @@ struct HTTP {
|
||||
int status_code; /* HTTP status code */
|
||||
const uint8_t *pausedata; /* pointer to data received in on_data_chunk */
|
||||
size_t pauselen; /* the number of bytes left in data */
|
||||
bool closed; /* TRUE on HTTP2 stream close */
|
||||
bool close_handled; /* TRUE if stream closure is handled by libcurl */
|
||||
char *mem; /* points to a buffer in memory to store received data */
|
||||
size_t len; /* size of the buffer 'mem' points to */
|
||||
size_t memlen; /* size of data copied to mem */
|
||||
|
||||
const uint8_t *upload_mem; /* points to a buffer to read from */
|
||||
size_t upload_len; /* size of the buffer 'upload_mem' points to */
|
||||
curl_off_t upload_left; /* number of bytes left to upload */
|
||||
|
||||
char **push_headers; /* allocated array */
|
||||
size_t push_headers_used; /* number of entries filled in */
|
||||
size_t push_headers_alloc; /* number of entries allocated */
|
||||
#endif
|
||||
#if defined(USE_NGHTTP2) || defined(USE_NGHTTP3)
|
||||
bool closed; /* TRUE on HTTP2 stream close */
|
||||
char *mem; /* points to a buffer in memory to store received data */
|
||||
size_t len; /* size of the buffer 'mem' points to */
|
||||
size_t memlen; /* size of data copied to mem */
|
||||
#endif
|
||||
#if defined(USE_NGHTTP2) || defined(ENABLE_QUIC)
|
||||
/* fields used by both HTTP/2 and HTTP/3 */
|
||||
const uint8_t *upload_mem; /* points to a buffer to read from */
|
||||
size_t upload_len; /* size of the buffer 'upload_mem' points to */
|
||||
curl_off_t upload_left; /* number of bytes left to upload */
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_QUIC
|
||||
/*********** for HTTP/3 we store stream-local data here *************/
|
||||
int64_t stream3_id; /* stream we are interested in */
|
||||
bool firstheader; /* FALSE until headers arrive */
|
||||
bool firstbody; /* FALSE until body arrives */
|
||||
bool h3req; /* FALSE until request is issued */
|
||||
bool upload_done;
|
||||
#endif
|
||||
#ifdef USE_NGHTTP3
|
||||
size_t unacked_window;
|
||||
struct h3out *h3out; /* per-stream buffers for upload */
|
||||
char *overflow_buf; /* excess data received during a single Curl_read */
|
||||
size_t overflow_buflen; /* amount of data currently in overflow_buf */
|
||||
size_t overflow_bufsize; /* size of the overflow_buf allocation */
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef USE_NGHTTP2
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2020, 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
|
||||
@ -43,19 +43,11 @@
|
||||
|
||||
#define H2_BUFSIZE 32768
|
||||
|
||||
#if (NGHTTP2_VERSION_NUM < 0x010000)
|
||||
#if (NGHTTP2_VERSION_NUM < 0x010c00)
|
||||
#error too old nghttp2 version, upgrade!
|
||||
#endif
|
||||
|
||||
#if (NGHTTP2_VERSION_NUM > 0x010800)
|
||||
#define NGHTTP2_HAS_HTTP2_STRERROR 1
|
||||
#endif
|
||||
|
||||
#if (NGHTTP2_VERSION_NUM >= 0x010900)
|
||||
/* nghttp2_session_callbacks_set_error_callback is present in nghttp2 1.9.0 or
|
||||
later */
|
||||
#define NGHTTP2_HAS_ERROR_CALLBACK 1
|
||||
#else
|
||||
#ifdef CURL_DISABLE_VERBOSE_STRINGS
|
||||
#define nghttp2_session_callbacks_set_error_callback(x,y)
|
||||
#endif
|
||||
|
||||
@ -63,12 +55,12 @@
|
||||
#define NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE 1
|
||||
#endif
|
||||
|
||||
#define HTTP2_HUGE_WINDOW_SIZE (1 << 30)
|
||||
#define HTTP2_HUGE_WINDOW_SIZE (32 * 1024 * 1024) /* 32 MB */
|
||||
|
||||
#ifdef DEBUG_HTTP2
|
||||
#define H2BUGF(x) x
|
||||
#else
|
||||
#define H2BUGF(x) do { } WHILE_FALSE
|
||||
#define H2BUGF(x) do { } while(0)
|
||||
#endif
|
||||
|
||||
|
||||
@ -100,16 +92,11 @@ void Curl_http2_init_userset(struct UserDefined *set)
|
||||
}
|
||||
|
||||
static int http2_perform_getsock(const struct connectdata *conn,
|
||||
curl_socket_t *sock, /* points to
|
||||
numsocks
|
||||
number of
|
||||
sockets */
|
||||
int numsocks)
|
||||
curl_socket_t *sock)
|
||||
{
|
||||
const struct http_conn *c = &conn->proto.httpc;
|
||||
struct SingleRequest *k = &conn->data->req;
|
||||
int bitmap = GETSOCK_BLANK;
|
||||
(void)numsocks;
|
||||
|
||||
sock[0] = conn->sock[FIRSTSOCKET];
|
||||
|
||||
@ -126,11 +113,9 @@ static int http2_perform_getsock(const struct connectdata *conn,
|
||||
}
|
||||
|
||||
static int http2_getsock(struct connectdata *conn,
|
||||
curl_socket_t *sock, /* points to numsocks
|
||||
number of sockets */
|
||||
int numsocks)
|
||||
curl_socket_t *socks)
|
||||
{
|
||||
return http2_perform_getsock(conn, sock, numsocks);
|
||||
return http2_perform_getsock(conn, socks);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -240,7 +225,7 @@ static unsigned int http2_conncheck(struct connectdata *check,
|
||||
|
||||
if(checks_to_perform & CONNCHECK_KEEPALIVE) {
|
||||
struct curltime now = Curl_now();
|
||||
time_t elapsed = Curl_timediff(now, check->keepalive);
|
||||
timediff_t elapsed = Curl_timediff(now, check->keepalive);
|
||||
|
||||
if(elapsed > check->upkeep_interval_ms) {
|
||||
/* Perform an HTTP/2 PING */
|
||||
@ -269,7 +254,7 @@ static unsigned int http2_conncheck(struct connectdata *check,
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/* called from Curl_http_setup_conn */
|
||||
/* called from http_setup_conn */
|
||||
void Curl_http2_setup_req(struct Curl_easy *data)
|
||||
{
|
||||
struct HTTP *http = data->req.protop;
|
||||
@ -286,7 +271,7 @@ void Curl_http2_setup_req(struct Curl_easy *data)
|
||||
http->memlen = 0;
|
||||
}
|
||||
|
||||
/* called from Curl_http_setup_conn */
|
||||
/* called from http_setup_conn */
|
||||
void Curl_http2_setup_conn(struct connectdata *conn)
|
||||
{
|
||||
conn->proto.httpc.settings.max_concurrent_streams =
|
||||
@ -351,35 +336,6 @@ int Curl_http2_ver(char *p, size_t len)
|
||||
return msnprintf(p, len, " nghttp2/%s", h2->version_str);
|
||||
}
|
||||
|
||||
/* HTTP/2 error code to name based on the Error Code Registry.
|
||||
https://tools.ietf.org/html/rfc7540#page-77
|
||||
nghttp2_error_code enums are identical.
|
||||
*/
|
||||
static const char *http2_strerror(uint32_t err)
|
||||
{
|
||||
#ifndef NGHTTP2_HAS_HTTP2_STRERROR
|
||||
const char *str[] = {
|
||||
"NO_ERROR", /* 0x0 */
|
||||
"PROTOCOL_ERROR", /* 0x1 */
|
||||
"INTERNAL_ERROR", /* 0x2 */
|
||||
"FLOW_CONTROL_ERROR", /* 0x3 */
|
||||
"SETTINGS_TIMEOUT", /* 0x4 */
|
||||
"STREAM_CLOSED", /* 0x5 */
|
||||
"FRAME_SIZE_ERROR", /* 0x6 */
|
||||
"REFUSED_STREAM", /* 0x7 */
|
||||
"CANCEL", /* 0x8 */
|
||||
"COMPRESSION_ERROR", /* 0x9 */
|
||||
"CONNECT_ERROR", /* 0xA */
|
||||
"ENHANCE_YOUR_CALM", /* 0xB */
|
||||
"INADEQUATE_SECURITY", /* 0xC */
|
||||
"HTTP_1_1_REQUIRED" /* 0xD */
|
||||
};
|
||||
return (err < sizeof(str) / sizeof(str[0])) ? str[err] : "unknown";
|
||||
#else
|
||||
return nghttp2_http2_strerror(err);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* The implementation of nghttp2_send_callback type. Here we write |data| with
|
||||
* size |length| to the network and return the number of bytes actually
|
||||
@ -503,16 +459,14 @@ static struct Curl_easy *duphandle(struct Curl_easy *data)
|
||||
/* setup the request struct */
|
||||
struct HTTP *http = calloc(1, sizeof(struct HTTP));
|
||||
if(!http) {
|
||||
(void)Curl_close(second);
|
||||
second = NULL;
|
||||
(void)Curl_close(&second);
|
||||
}
|
||||
else {
|
||||
second->req.protop = http;
|
||||
http->header_recvbuf = Curl_add_buffer_init();
|
||||
if(!http->header_recvbuf) {
|
||||
free(http);
|
||||
(void)Curl_close(second);
|
||||
second = NULL;
|
||||
(void)Curl_close(&second);
|
||||
}
|
||||
else {
|
||||
Curl_http2_setup_req(second);
|
||||
@ -554,7 +508,7 @@ static int push_promise(struct Curl_easy *data,
|
||||
stream = data->req.protop;
|
||||
if(!stream) {
|
||||
failf(data, "Internal NULL stream!\n");
|
||||
(void)Curl_close(newhandle);
|
||||
(void)Curl_close(&newhandle);
|
||||
rv = 1;
|
||||
goto fail;
|
||||
}
|
||||
@ -576,7 +530,7 @@ static int push_promise(struct Curl_easy *data,
|
||||
/* denied, kill off the new handle again */
|
||||
http2_stream_free(newhandle->req.protop);
|
||||
newhandle->req.protop = NULL;
|
||||
(void)Curl_close(newhandle);
|
||||
(void)Curl_close(&newhandle);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -592,7 +546,7 @@ static int push_promise(struct Curl_easy *data,
|
||||
infof(data, "failed to add handle to multi\n");
|
||||
http2_stream_free(newhandle->req.protop);
|
||||
newhandle->req.protop = NULL;
|
||||
Curl_close(newhandle);
|
||||
Curl_close(&newhandle);
|
||||
rv = 1;
|
||||
goto fail;
|
||||
}
|
||||
@ -847,7 +801,7 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
|
||||
return 0;
|
||||
}
|
||||
H2BUGF(infof(data_s, "on_stream_close(), %s (err %d), stream %u\n",
|
||||
http2_strerror(error_code), error_code, stream_id));
|
||||
nghttp2_strerror(error_code), error_code, stream_id));
|
||||
stream = data_s->req.protop;
|
||||
if(!stream)
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
@ -855,6 +809,7 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
|
||||
stream->closed = TRUE;
|
||||
httpc = &conn->proto.httpc;
|
||||
drain_this(data_s, httpc);
|
||||
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
|
||||
httpc->error_code = error_code;
|
||||
|
||||
/* remove the entry from the hash as the stream is now gone */
|
||||
@ -974,7 +929,9 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
|
||||
if(!check)
|
||||
/* no memory */
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
if(!Curl_strcasecompare(check, (const char *)value)) {
|
||||
if(!Curl_strcasecompare(check, (const char *)value) &&
|
||||
((conn->remote_port != conn->given->defport) ||
|
||||
!Curl_strcasecompare(conn->host.name, (const char *)value))) {
|
||||
/* This is push is not for the same authority that was asked for in
|
||||
* the URL. RFC 7540 section 8.2 says: "A client MUST treat a
|
||||
* PUSH_PROMISE for which the server is not authoritative as a stream
|
||||
@ -1144,8 +1101,7 @@ static ssize_t data_source_read_callback(nghttp2_session *session,
|
||||
return nread;
|
||||
}
|
||||
|
||||
#if defined(NGHTTP2_HAS_ERROR_CALLBACK) && \
|
||||
!defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
static int error_callback(nghttp2_session *session,
|
||||
const char *msg,
|
||||
size_t len,
|
||||
@ -1162,9 +1118,10 @@ static void populate_settings(struct connectdata *conn,
|
||||
struct http_conn *httpc)
|
||||
{
|
||||
nghttp2_settings_entry *iv = httpc->local_settings;
|
||||
DEBUGASSERT(conn->data);
|
||||
|
||||
iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
|
||||
iv[0].value = 100;
|
||||
iv[0].value = Curl_multi_max_concurrent_streams(conn->data->multi);
|
||||
|
||||
iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
|
||||
iv[1].value = HTTP2_HUGE_WINDOW_SIZE;
|
||||
@ -1175,11 +1132,10 @@ static void populate_settings(struct connectdata *conn,
|
||||
httpc->local_settings_num = 3;
|
||||
}
|
||||
|
||||
void Curl_http2_done(struct connectdata *conn, bool premature)
|
||||
void Curl_http2_done(struct Curl_easy *data, bool premature)
|
||||
{
|
||||
struct Curl_easy *data = conn->data;
|
||||
struct HTTP *http = data->req.protop;
|
||||
struct http_conn *httpc = &conn->proto.httpc;
|
||||
struct http_conn *httpc = &data->conn->proto.httpc;
|
||||
|
||||
/* there might be allocated resources done before this got the 'h2' pointer
|
||||
setup */
|
||||
@ -1199,9 +1155,6 @@ void Curl_http2_done(struct connectdata *conn, bool premature)
|
||||
if(!httpc->h2) /* not HTTP/2 ? */
|
||||
return;
|
||||
|
||||
if(data->state.drain)
|
||||
drained_transfer(data, httpc);
|
||||
|
||||
if(premature) {
|
||||
/* RST_STREAM */
|
||||
if(!nghttp2_submit_rst_stream(httpc->h2, NGHTTP2_FLAG_NONE,
|
||||
@ -1213,6 +1166,10 @@ void Curl_http2_done(struct connectdata *conn, bool premature)
|
||||
httpc->pause_stream_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(data->state.drain)
|
||||
drained_transfer(data, httpc);
|
||||
|
||||
/* -1 means unassigned and 0 means cleared */
|
||||
if(http->stream_id > 0) {
|
||||
int rv = nghttp2_session_set_stream_user_data(httpc->h2,
|
||||
@ -1263,9 +1220,7 @@ static CURLcode http2_init(struct connectdata *conn)
|
||||
/* nghttp2_on_header_callback */
|
||||
nghttp2_session_callbacks_set_on_header_callback(callbacks, on_header);
|
||||
|
||||
#ifndef CURL_DISABLE_VERBOSE_STRINGS
|
||||
nghttp2_session_callbacks_set_error_callback(callbacks, error_callback);
|
||||
#endif
|
||||
|
||||
/* The nghttp2 session is not yet setup, do it */
|
||||
rc = nghttp2_session_client_new(&conn->proto.httpc.h2, callbacks, conn);
|
||||
@ -1463,7 +1418,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
|
||||
}
|
||||
else if(httpc->error_code != NGHTTP2_NO_ERROR) {
|
||||
failf(data, "HTTP/2 stream %d was not closed cleanly: %s (err %u)",
|
||||
stream->stream_id, http2_strerror(httpc->error_code),
|
||||
stream->stream_id, nghttp2_strerror(httpc->error_code),
|
||||
httpc->error_code);
|
||||
*err = CURLE_HTTP2_STREAM;
|
||||
return -1;
|
||||
@ -1541,6 +1496,7 @@ static int h2_session_send(struct Curl_easy *data,
|
||||
|
||||
H2BUGF(infof(data, "Queuing PRIORITY on stream %u (easy %p)\n",
|
||||
stream->stream_id, data));
|
||||
DEBUGASSERT(stream->stream_id != -1);
|
||||
rv = nghttp2_submit_priority(h2, NGHTTP2_FLAG_NONE, stream->stream_id,
|
||||
&pri_spec);
|
||||
if(rv)
|
||||
@ -1565,6 +1521,11 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
|
||||
if(should_close_session(httpc)) {
|
||||
H2BUGF(infof(data,
|
||||
"http2_recv: nothing to do in this session\n"));
|
||||
if(conn->bits.close) {
|
||||
/* already marked for closure, return OK and we're done */
|
||||
*err = CURLE_OK;
|
||||
return 0;
|
||||
}
|
||||
*err = CURLE_HTTP2;
|
||||
return -1;
|
||||
}
|
||||
@ -1594,8 +1555,12 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
|
||||
return ncopy;
|
||||
}
|
||||
|
||||
H2BUGF(infof(data, "http2_recv: easy %p (stream %u)\n",
|
||||
data, stream->stream_id));
|
||||
H2BUGF(infof(data, "http2_recv: easy %p (stream %u) win %u/%u\n",
|
||||
data, stream->stream_id,
|
||||
nghttp2_session_get_local_window_size(httpc->h2),
|
||||
nghttp2_session_get_stream_local_window_size(httpc->h2,
|
||||
stream->stream_id)
|
||||
));
|
||||
|
||||
if((data->state.drain) && stream->memlen) {
|
||||
H2BUGF(infof(data, "http2_recv: DRAIN %zu bytes stream %u!! (%p => %p)\n",
|
||||
@ -1626,7 +1591,6 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
|
||||
stream->pausedata += nread;
|
||||
stream->pauselen -= nread;
|
||||
|
||||
infof(data, "%zd data bytes written\n", nread);
|
||||
if(stream->pauselen == 0) {
|
||||
H2BUGF(infof(data, "Unpaused by stream %u\n", stream->stream_id));
|
||||
DEBUGASSERT(httpc->pause_stream_id == stream->stream_id);
|
||||
@ -1660,6 +1624,9 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
|
||||
socket is not read. But it seems that usually streams are
|
||||
notified with its drain property, and socket is read again
|
||||
quickly. */
|
||||
if(stream->closed)
|
||||
/* closed overrides paused */
|
||||
return 0;
|
||||
H2BUGF(infof(data, "stream %x is paused, pause id: %x\n",
|
||||
stream->stream_id, httpc->pause_stream_id));
|
||||
*err = CURLE_AGAIN;
|
||||
@ -1754,14 +1721,16 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
|
||||
else if(!stream->closed) {
|
||||
drained_transfer(data, httpc);
|
||||
}
|
||||
else
|
||||
/* this stream is closed, trigger a another read ASAP to detect that */
|
||||
Curl_expire(data, 0, EXPIRE_RUN_NOW);
|
||||
|
||||
return retlen;
|
||||
}
|
||||
/* If stream is closed, return 0 to signal the http routine to close
|
||||
/* If this stream is closed, return 0 to signal the http routine to close
|
||||
the connection */
|
||||
if(stream->closed) {
|
||||
return http2_handle_stream_close(conn, data, stream, err);
|
||||
}
|
||||
if(stream->closed)
|
||||
return 0;
|
||||
*err = CURLE_AGAIN;
|
||||
H2BUGF(infof(data, "http2_recv returns AGAIN for stream %u\n",
|
||||
stream->stream_id));
|
||||
@ -1772,8 +1741,9 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
|
||||
field list. */
|
||||
#define AUTHORITY_DST_IDX 3
|
||||
|
||||
/* USHRT_MAX is 65535 == 0xffff */
|
||||
#define HEADER_OVERFLOW(x) \
|
||||
(x.namelen > (uint16_t)-1 || x.valuelen > (uint16_t)-1 - x.namelen)
|
||||
(x.namelen > 0xffff || x.valuelen > 0xffff - x.namelen)
|
||||
|
||||
/*
|
||||
* Check header memory for the token "trailers".
|
||||
@ -1880,7 +1850,11 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
|
||||
are going to send or sending request body in DATA frame */
|
||||
stream->upload_mem = mem;
|
||||
stream->upload_len = len;
|
||||
nghttp2_session_resume_data(h2, stream->stream_id);
|
||||
rv = nghttp2_session_resume_data(h2, stream->stream_id);
|
||||
if(nghttp2_is_fatal(rv)) {
|
||||
*err = CURLE_SEND_ERROR;
|
||||
return -1;
|
||||
}
|
||||
rv = h2_session_send(conn->data, h2);
|
||||
if(nghttp2_is_fatal(rv)) {
|
||||
*err = CURLE_SEND_ERROR;
|
||||
@ -2019,8 +1993,10 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
|
||||
nva[i].namelen = strlen((char *)nva[i].name);
|
||||
}
|
||||
else {
|
||||
nva[i].name = (unsigned char *)hdbuf;
|
||||
nva[i].namelen = (size_t)(end - hdbuf);
|
||||
/* Lower case the header name for HTTP/2 */
|
||||
Curl_strntolower((char *)hdbuf, hdbuf, nva[i].namelen);
|
||||
nva[i].name = (unsigned char *)hdbuf;
|
||||
}
|
||||
hdbuf = end + 1;
|
||||
while(*hdbuf == ' ' || *hdbuf == '\t')
|
||||
@ -2130,17 +2106,14 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(stream->stream_id != -1) {
|
||||
/* If whole HEADERS frame was sent off to the underlying socket,
|
||||
the nghttp2 library calls data_source_read_callback. But only
|
||||
it found that no data available, so it deferred the DATA
|
||||
transmission. Which means that nghttp2_session_want_write()
|
||||
returns 0 on http2_perform_getsock(), which results that no
|
||||
writable socket check is performed. To workaround this, we
|
||||
issue nghttp2_session_resume_data() here to bring back DATA
|
||||
transmission from deferred state. */
|
||||
nghttp2_session_resume_data(h2, stream->stream_id);
|
||||
}
|
||||
/* If whole HEADERS frame was sent off to the underlying socket, the nghttp2
|
||||
library calls data_source_read_callback. But only it found that no data
|
||||
available, so it deferred the DATA transmission. Which means that
|
||||
nghttp2_session_want_write() returns 0 on http2_perform_getsock(), which
|
||||
results that no writable socket check is performed. To workaround this,
|
||||
we issue nghttp2_session_resume_data() here to bring back DATA
|
||||
transmission from deferred state. */
|
||||
nghttp2_session_resume_data(h2, stream->stream_id);
|
||||
|
||||
return len;
|
||||
|
||||
@ -2255,7 +2228,6 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE
|
||||
rv = nghttp2_session_set_local_window_size(httpc->h2, NGHTTP2_FLAG_NONE, 0,
|
||||
HTTP2_HUGE_WINDOW_SIZE);
|
||||
if(rv != 0) {
|
||||
@ -2263,7 +2235,6 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
|
||||
nghttp2_strerror(rv), rv);
|
||||
return CURLE_HTTP2;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* we are going to copy mem to httpc->inbuf. This is required since
|
||||
mem is part of buffer pointed by stream->mem, and callbacks
|
||||
@ -2321,6 +2292,51 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
CURLcode Curl_http2_stream_pause(struct Curl_easy *data, bool pause)
|
||||
{
|
||||
DEBUGASSERT(data);
|
||||
DEBUGASSERT(data->conn);
|
||||
/* if it isn't HTTP/2, we're done */
|
||||
if(!data->conn->proto.httpc.h2)
|
||||
return CURLE_OK;
|
||||
#ifdef NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE
|
||||
else {
|
||||
struct HTTP *stream = data->req.protop;
|
||||
struct http_conn *httpc = &data->conn->proto.httpc;
|
||||
uint32_t window = !pause * HTTP2_HUGE_WINDOW_SIZE;
|
||||
int rv = nghttp2_session_set_local_window_size(httpc->h2,
|
||||
NGHTTP2_FLAG_NONE,
|
||||
stream->stream_id,
|
||||
window);
|
||||
if(rv) {
|
||||
failf(data, "nghttp2_session_set_local_window_size() failed: %s(%d)",
|
||||
nghttp2_strerror(rv), rv);
|
||||
return CURLE_HTTP2;
|
||||
}
|
||||
|
||||
/* make sure the window update gets sent */
|
||||
rv = h2_session_send(data, httpc->h2);
|
||||
if(rv)
|
||||
return CURLE_SEND_ERROR;
|
||||
|
||||
DEBUGF(infof(data, "Set HTTP/2 window size to %u for stream %u\n",
|
||||
window, stream->stream_id));
|
||||
|
||||
#ifdef DEBUGBUILD
|
||||
{
|
||||
/* read out the stream local window again */
|
||||
uint32_t window2 =
|
||||
nghttp2_session_get_stream_local_window_size(httpc->h2,
|
||||
stream->stream_id);
|
||||
DEBUGF(infof(data, "HTTP/2 window size is now %u for stream %u\n",
|
||||
window2, stream->stream_id));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
CURLcode Curl_http2_add_child(struct Curl_easy *parent,
|
||||
struct Curl_easy *child,
|
||||
bool exclusive)
|
||||
@ -2414,8 +2430,6 @@ bool Curl_h2_http_1_1_error(struct connectdata *conn)
|
||||
#else /* !USE_NGHTTP2 */
|
||||
|
||||
/* Satisfy external references even if http2 is not compiled in. */
|
||||
|
||||
#define CURL_DISABLE_TYPECHECK
|
||||
#include <curl/curl.h>
|
||||
|
||||
char *curl_pushheader_bynum(struct curl_pushheaders *h, size_t num)
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2020, 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
|
||||
@ -42,16 +42,15 @@ const char *Curl_http2_strerror(uint32_t err);
|
||||
CURLcode Curl_http2_init(struct connectdata *conn);
|
||||
void Curl_http2_init_state(struct UrlState *state);
|
||||
void Curl_http2_init_userset(struct UserDefined *set);
|
||||
CURLcode Curl_http2_send_request(struct connectdata *conn);
|
||||
CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req,
|
||||
struct connectdata *conn);
|
||||
CURLcode Curl_http2_setup(struct connectdata *conn);
|
||||
CURLcode Curl_http2_switched(struct connectdata *conn,
|
||||
const char *data, size_t nread);
|
||||
/* called from Curl_http_setup_conn */
|
||||
/* called from http_setup_conn */
|
||||
void Curl_http2_setup_conn(struct connectdata *conn);
|
||||
void Curl_http2_setup_req(struct Curl_easy *data);
|
||||
void Curl_http2_done(struct connectdata *conn, bool premature);
|
||||
void Curl_http2_done(struct Curl_easy *data, bool premature);
|
||||
CURLcode Curl_http2_done_sending(struct connectdata *conn);
|
||||
CURLcode Curl_http2_add_child(struct Curl_easy *parent,
|
||||
struct Curl_easy *child,
|
||||
@ -59,11 +58,11 @@ CURLcode Curl_http2_add_child(struct Curl_easy *parent,
|
||||
void Curl_http2_remove_child(struct Curl_easy *parent,
|
||||
struct Curl_easy *child);
|
||||
void Curl_http2_cleanup_dependencies(struct Curl_easy *data);
|
||||
CURLcode Curl_http2_stream_pause(struct Curl_easy *data, bool pause);
|
||||
|
||||
/* returns true if the HTTP/2 stream error was HTTP_1_1_REQUIRED */
|
||||
bool Curl_h2_http_1_1_error(struct connectdata *conn);
|
||||
#else /* USE_NGHTTP2 */
|
||||
#define Curl_http2_send_request(x) CURLE_UNSUPPORTED_PROTOCOL
|
||||
#define Curl_http2_request_upgrade(x,y) CURLE_UNSUPPORTED_PROTOCOL
|
||||
#define Curl_http2_setup(x) CURLE_UNSUPPORTED_PROTOCOL
|
||||
#define Curl_http2_switched(x,y,z) CURLE_UNSUPPORTED_PROTOCOL
|
||||
@ -76,6 +75,7 @@ bool Curl_h2_http_1_1_error(struct connectdata *conn);
|
||||
#define Curl_http2_add_child(x, y, z)
|
||||
#define Curl_http2_remove_child(x, y)
|
||||
#define Curl_http2_cleanup_dependencies(x)
|
||||
#define Curl_http2_stream_pause(x, y)
|
||||
#define Curl_h2_http_1_1_error(x) 0
|
||||
#endif
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2019, 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
|
||||
@ -109,7 +109,8 @@ void Curl_httpchunk_init(struct connectdata *conn)
|
||||
CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
|
||||
char *datap,
|
||||
ssize_t datalen,
|
||||
ssize_t *wrotep)
|
||||
ssize_t *wrotep,
|
||||
CURLcode *extrap)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct Curl_easy *data = conn->data;
|
||||
@ -125,8 +126,10 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
|
||||
chunk read process, to properly calculate the content length*/
|
||||
if(data->set.http_te_skip && !k->ignorebody) {
|
||||
result = Curl_client_write(conn, CLIENTWRITE_BODY, datap, datalen);
|
||||
if(result)
|
||||
return CHUNKE_WRITE_ERROR;
|
||||
if(result) {
|
||||
*extrap = result;
|
||||
return CHUNKE_PASSTHRU_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
while(length) {
|
||||
@ -197,8 +200,10 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
|
||||
else
|
||||
result = Curl_client_write(conn, CLIENTWRITE_BODY, datap, piece);
|
||||
|
||||
if(result)
|
||||
return CHUNKE_WRITE_ERROR;
|
||||
if(result) {
|
||||
*extrap = result;
|
||||
return CHUNKE_PASSTHRU_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
*wrote += piece;
|
||||
@ -244,8 +249,10 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
|
||||
if(!data->set.http_te_skip) {
|
||||
result = Curl_client_write(conn, CLIENTWRITE_HEADER,
|
||||
conn->trailer, conn->trlPos);
|
||||
if(result)
|
||||
return CHUNKE_WRITE_ERROR;
|
||||
if(result) {
|
||||
*extrap = result;
|
||||
return CHUNKE_PASSTHRU_ERROR;
|
||||
}
|
||||
}
|
||||
conn->trlPos = 0;
|
||||
ch->state = CHUNK_TRAILER_CR;
|
||||
@ -339,8 +346,9 @@ const char *Curl_chunked_strerror(CHUNKcode code)
|
||||
return "Illegal or missing hexadecimal sequence";
|
||||
case CHUNKE_BAD_CHUNK:
|
||||
return "Malformed encoding found";
|
||||
case CHUNKE_WRITE_ERROR:
|
||||
return "Write error";
|
||||
case CHUNKE_PASSTHRU_ERROR:
|
||||
DEBUGASSERT(0); /* never used */
|
||||
return "";
|
||||
case CHUNKE_BAD_ENCODING:
|
||||
return "Bad content-encoding found";
|
||||
case CHUNKE_OUT_OF_MEMORY:
|
||||
|
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2019, 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
|
||||
@ -21,6 +21,9 @@
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
struct connectdata;
|
||||
|
||||
/*
|
||||
* The longest possible hexadecimal number we support in a chunked transfer.
|
||||
* Weird enough, RFC2616 doesn't set a maximum size! Since we use strtoul()
|
||||
@ -71,9 +74,9 @@ typedef enum {
|
||||
CHUNKE_TOO_LONG_HEX = 1,
|
||||
CHUNKE_ILLEGAL_HEX,
|
||||
CHUNKE_BAD_CHUNK,
|
||||
CHUNKE_WRITE_ERROR,
|
||||
CHUNKE_BAD_ENCODING,
|
||||
CHUNKE_OUT_OF_MEMORY,
|
||||
CHUNKE_PASSTHRU_ERROR, /* Curl_httpchunk_read() returns a CURLcode to use */
|
||||
CHUNKE_LAST
|
||||
} CHUNKcode;
|
||||
|
||||
@ -87,4 +90,10 @@ struct Curl_chunker {
|
||||
size_t dataleft; /* untouched data amount at the end of the last buffer */
|
||||
};
|
||||
|
||||
/* The following functions are defined in http_chunks.c */
|
||||
void Curl_httpchunk_init(struct connectdata *conn);
|
||||
CHUNKcode Curl_httpchunk_read(struct connectdata *conn, char *datap,
|
||||
ssize_t length, ssize_t *wrote,
|
||||
CURLcode *passthru);
|
||||
|
||||
#endif /* HEADER_CURL_HTTP_CHUNKS_H */
|
||||
|
@ -148,10 +148,10 @@ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
|
||||
}
|
||||
if(!neg_ctx->context) {
|
||||
result = Curl_input_negotiate(conn, proxy, "Negotiate");
|
||||
if(result == CURLE_LOGIN_DENIED) {
|
||||
if(result == CURLE_AUTH_ERROR) {
|
||||
/* negotiate auth failed, let's continue unauthenticated to stay
|
||||
* compatible with the behavior before curl-7_64_0-158-g6c6035532 */
|
||||
conn->data->state.authproblem = TRUE;
|
||||
authp->done = TRUE;
|
||||
return CURLE_OK;
|
||||
}
|
||||
else if(result)
|
||||
|
@ -44,9 +44,7 @@
|
||||
|
||||
/* 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"
|
||||
#elif defined(USE_WINDOWS_SSPI)
|
||||
#if defined(USE_WINDOWS_SSPI)
|
||||
#include "curl_sspi.h"
|
||||
#endif
|
||||
|
||||
@ -137,11 +135,6 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
|
||||
DEBUGASSERT(conn);
|
||||
DEBUGASSERT(conn->data);
|
||||
|
||||
#if defined(NTLM_NEEDS_NSS_INIT)
|
||||
if(CURLE_OK != Curl_nss_force_init(conn->data))
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
#endif
|
||||
|
||||
if(proxy) {
|
||||
allocuserpwd = &conn->allocptr.proxyuserpwd;
|
||||
userp = conn->http_proxy.user;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user