Windows: update libcurl dependency

Update bundled libcurl.
Only used on Windows. On Linux and OSX we use system libraries.
This commit is contained in:
Floris Bos 2023-03-24 14:13:35 +01:00
parent a97de5c703
commit 0378751295
370 changed files with 68199 additions and 38210 deletions

View file

@ -0,0 +1 @@
* -whitespace

View file

@ -1 +1,24 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
@CMAKE_CONFIGURABLE_FILE_CONTENT@ @CMAKE_CONFIGURABLE_FILE_CONTENT@

View file

@ -1,3 +1,26 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
include(CheckCSourceCompiles) include(CheckCSourceCompiles)
option(CURL_HIDDEN_SYMBOLS "Set to ON to hide libcurl internal symbols (=hide all symbols that aren't officially external)." ON) option(CURL_HIDDEN_SYMBOLS "Set to ON to hide libcurl internal symbols (=hide all symbols that aren't officially external)." ON)
@ -6,18 +29,12 @@ mark_as_advanced(CURL_HIDDEN_SYMBOLS)
if(CURL_HIDDEN_SYMBOLS) if(CURL_HIDDEN_SYMBOLS)
set(SUPPORTS_SYMBOL_HIDING FALSE) set(SUPPORTS_SYMBOL_HIDING FALSE)
if(CMAKE_C_COMPILER_ID MATCHES "Clang") if(CMAKE_C_COMPILER_ID MATCHES "Clang" AND NOT MSVC)
set(SUPPORTS_SYMBOL_HIDING TRUE) set(SUPPORTS_SYMBOL_HIDING TRUE)
set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))") set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden") set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
elseif(CMAKE_COMPILER_IS_GNUCC) elseif(CMAKE_COMPILER_IS_GNUCC)
if(NOT CMAKE_VERSION VERSION_LESS 2.8.10) if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4)
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)
# note: this is considered buggy prior to 4.0 but the autotools don't care, so let's ignore that fact # 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(SUPPORTS_SYMBOL_HIDING TRUE)
set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))") set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
@ -29,7 +46,7 @@ if(CURL_HIDDEN_SYMBOLS)
set(_CFLAG_SYMBOLS_HIDE "-xldscope=hidden") set(_CFLAG_SYMBOLS_HIDE "-xldscope=hidden")
elseif(CMAKE_C_COMPILER_ID MATCHES "Intel" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 9.0) 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 # 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(SUPPORTS_SYMBOL_HIDING TRUE)
set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))") set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden") set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")

View file

@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#ifdef TIME_WITH_SYS_TIME #ifdef TIME_WITH_SYS_TIME
/* Time with sys/time test */ /* Time with sys/time test */
@ -56,7 +58,7 @@ return 0;
# define PLATFORM_AIX_V3 # define PLATFORM_AIX_V3
#endif #endif
/* */ /* */
#if defined(PLATFORM_SUNOS4) || defined(PLATFORM_AIX_V3) || defined(__BEOS__) #if defined(PLATFORM_SUNOS4) || defined(PLATFORM_AIX_V3)
#error "O_NONBLOCK does not work on this platform" #error "O_NONBLOCK does not work on this platform"
#endif #endif
@ -71,21 +73,15 @@ main ()
} }
#endif #endif
/* tests for gethostbyaddr_r or gethostbyname_r */ /* tests for gethostbyname_r */
#if defined(HAVE_GETHOSTBYADDR_R_5_REENTRANT) || \ #if defined(HAVE_GETHOSTBYNAME_R_3_REENTRANT) || \
defined(HAVE_GETHOSTBYADDR_R_7_REENTRANT) || \
defined(HAVE_GETHOSTBYADDR_R_8_REENTRANT) || \
defined(HAVE_GETHOSTBYNAME_R_3_REENTRANT) || \
defined(HAVE_GETHOSTBYNAME_R_5_REENTRANT) || \ defined(HAVE_GETHOSTBYNAME_R_5_REENTRANT) || \
defined(HAVE_GETHOSTBYNAME_R_6_REENTRANT) defined(HAVE_GETHOSTBYNAME_R_6_REENTRANT)
# define _REENTRANT # define _REENTRANT
/* no idea whether _REENTRANT is always set, just invent a new flag */ /* no idea whether _REENTRANT is always set, just invent a new flag */
# define TEST_GETHOSTBYFOO_REENTRANT # define TEST_GETHOSTBYFOO_REENTRANT
#endif #endif
#if defined(HAVE_GETHOSTBYADDR_R_5) || \ #if defined(HAVE_GETHOSTBYNAME_R_3) || \
defined(HAVE_GETHOSTBYADDR_R_7) || \
defined(HAVE_GETHOSTBYADDR_R_8) || \
defined(HAVE_GETHOSTBYNAME_R_3) || \
defined(HAVE_GETHOSTBYNAME_R_5) || \ defined(HAVE_GETHOSTBYNAME_R_5) || \
defined(HAVE_GETHOSTBYNAME_R_6) || \ defined(HAVE_GETHOSTBYNAME_R_6) || \
defined(TEST_GETHOSTBYFOO_REENTRANT) defined(TEST_GETHOSTBYFOO_REENTRANT)
@ -98,18 +94,10 @@ int main(void)
int type = 0; int type = 0;
struct hostent h; struct hostent h;
int rc = 0; int rc = 0;
#if defined(HAVE_GETHOSTBYADDR_R_5) || \ #if defined(HAVE_GETHOSTBYNAME_R_3) || \
defined(HAVE_GETHOSTBYADDR_R_5_REENTRANT) || \
\
defined(HAVE_GETHOSTBYNAME_R_3) || \
defined(HAVE_GETHOSTBYNAME_R_3_REENTRANT) defined(HAVE_GETHOSTBYNAME_R_3_REENTRANT)
struct hostent_data hdata; struct hostent_data hdata;
#elif defined(HAVE_GETHOSTBYADDR_R_7) || \ #elif defined(HAVE_GETHOSTBYNAME_R_5) || \
defined(HAVE_GETHOSTBYADDR_R_7_REENTRANT) || \
defined(HAVE_GETHOSTBYADDR_R_8) || \
defined(HAVE_GETHOSTBYADDR_R_8_REENTRANT) || \
\
defined(HAVE_GETHOSTBYNAME_R_5) || \
defined(HAVE_GETHOSTBYNAME_R_5_REENTRANT) || \ defined(HAVE_GETHOSTBYNAME_R_5_REENTRANT) || \
defined(HAVE_GETHOSTBYNAME_R_6) || \ defined(HAVE_GETHOSTBYNAME_R_6) || \
defined(HAVE_GETHOSTBYNAME_R_6_REENTRANT) defined(HAVE_GETHOSTBYNAME_R_6_REENTRANT)
@ -118,22 +106,6 @@ int main(void)
struct hostent *hp; struct hostent *hp;
#endif #endif
#ifndef gethostbyaddr_r
(void)gethostbyaddr_r;
#endif
#if defined(HAVE_GETHOSTBYADDR_R_5) || \
defined(HAVE_GETHOSTBYADDR_R_5_REENTRANT)
rc = gethostbyaddr_r(address, length, type, &h, &hdata);
#elif defined(HAVE_GETHOSTBYADDR_R_7) || \
defined(HAVE_GETHOSTBYADDR_R_7_REENTRANT)
hp = gethostbyaddr_r(address, length, type, &h, buffer, 8192, &h_errnop);
(void)hp;
#elif defined(HAVE_GETHOSTBYADDR_R_8) || \
defined(HAVE_GETHOSTBYADDR_R_8_REENTRANT)
rc = gethostbyaddr_r(address, length, type, &h, buffer, 8192, &hp, &h_errnop);
#endif
#if defined(HAVE_GETHOSTBYNAME_R_3) || \ #if defined(HAVE_GETHOSTBYNAME_R_3) || \
defined(HAVE_GETHOSTBYNAME_R_3_REENTRANT) defined(HAVE_GETHOSTBYNAME_R_3_REENTRANT)
rc = gethostbyname_r(address, &h, &hdata); rc = gethostbyname_r(address, &h, &hdata);
@ -212,77 +184,6 @@ if (sizeof (bool *) )
#include <float.h> #include <float.h>
int main() { return 0; } int main() { return 0; }
#endif #endif
#ifdef RETSIGTYPE_TEST
#include <sys/types.h>
#include <signal.h>
#ifdef signal
# undef signal
#endif
#ifdef __cplusplus
extern "C" void (*signal (int, void (*)(int)))(int);
#else
void (*signal ()) ();
#endif
int
main ()
{
return 0;
}
#endif
#ifdef HAVE_INET_NTOA_R_DECL
#include <arpa/inet.h>
typedef void (*func_type)();
int main()
{
#ifndef inet_ntoa_r
func_type func;
func = (func_type)inet_ntoa_r;
(void)func;
#endif
return 0;
}
#endif
#ifdef HAVE_INET_NTOA_R_DECL_REENTRANT
#define _REENTRANT
#include <arpa/inet.h>
typedef void (*func_type)();
int main()
{
#ifndef inet_ntoa_r
func_type func;
func = (func_type)&inet_ntoa_r;
(void)func;
#endif
return 0;
}
#endif
#ifdef HAVE_GETADDRINFO
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
int main(void) {
struct addrinfo hints, *ai;
int error;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
#ifndef getaddrinfo
(void)getaddrinfo;
#endif
error = getaddrinfo("127.0.0.1", "8080", &hints, &ai);
if (error) {
return 1;
}
return 0;
}
#endif
#ifdef HAVE_FILE_OFFSET_BITS #ifdef HAVE_FILE_OFFSET_BITS
#ifdef _FILE_OFFSET_BITS #ifdef _FILE_OFFSET_BITS
#undef _FILE_OFFSET_BITS #undef _FILE_OFFSET_BITS
@ -308,10 +209,6 @@ int main () { ; return 0; }
# include <windows.h> # include <windows.h>
# ifdef HAVE_WINSOCK2_H # ifdef HAVE_WINSOCK2_H
# include <winsock2.h> # include <winsock2.h>
# else
# ifdef HAVE_WINSOCK_H
# include <winsock.h>
# endif
# endif # endif
#endif #endif
@ -337,10 +234,6 @@ main ()
# include <windows.h> # include <windows.h>
# ifdef HAVE_WINSOCK2_H # ifdef HAVE_WINSOCK2_H
# include <winsock2.h> # include <winsock2.h>
# else
# ifdef HAVE_WINSOCK_H
# include <winsock.h>
# endif
# endif # endif
#endif #endif
@ -364,10 +257,6 @@ main ()
# include <windows.h> # include <windows.h>
# ifdef HAVE_WINSOCK2_H # ifdef HAVE_WINSOCK2_H
# include <winsock2.h> # include <winsock2.h>
# else
# ifdef HAVE_WINSOCK_H
# include <winsock.h>
# endif
# endif # endif
#endif #endif
@ -377,7 +266,7 @@ main ()
/* IoctlSocket source code */ /* IoctlSocket source code */
long flags = 0; long flags = 0;
if(0 != ioctlsocket(0, FIONBIO, &flags)) if(0 != IoctlSocket(0, FIONBIO, &flags))
return 1; return 1;
; ;
return 0; return 0;
@ -392,10 +281,6 @@ main ()
# include <windows.h> # include <windows.h>
# ifdef HAVE_WINSOCK2_H # ifdef HAVE_WINSOCK2_H
# include <winsock2.h> # include <winsock2.h>
# else
# ifdef HAVE_WINSOCK_H
# include <winsock.h>
# endif
# endif # endif
#endif #endif
@ -482,10 +367,6 @@ main ()
# include <windows.h> # include <windows.h>
# ifdef HAVE_WINSOCK2_H # ifdef HAVE_WINSOCK2_H
# include <winsock2.h> # include <winsock2.h>
# else
# ifdef HAVE_WINSOCK_H
# include <winsock.h>
# endif
# endif # endif
#endif #endif
/* includes start */ /* includes start */
@ -613,3 +494,39 @@ main() {
return 0; return 0;
} }
#endif #endif
#ifdef HAVE_ATOMIC
/* includes start */
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_STDATOMIC_H
# include <stdatomic.h>
#endif
/* includes end */
int
main() {
_Atomic int i = 1;
i = 0; // Force an atomic-write operation.
return i;
}
#endif
#ifdef HAVE_WIN32_WINNT
/* includes start */
#ifdef WIN32
# include "../lib/setup-win32.h"
#endif
/* includes end */
#define enquote(x) #x
#define expand(x) enquote(x)
#pragma message("_WIN32_WINNT=" expand(_WIN32_WINNT))
int
main() {
return 0;
}
#endif

View file

@ -0,0 +1,32 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
find_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)

View file

@ -1,3 +1,26 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
include(FindPackageHandleStandardArgs) include(FindPackageHandleStandardArgs)
find_path(BROTLI_INCLUDE_DIR "brotli/decode.h") find_path(BROTLI_INCLUDE_DIR "brotli/decode.h")
@ -5,7 +28,7 @@ find_path(BROTLI_INCLUDE_DIR "brotli/decode.h")
find_library(BROTLICOMMON_LIBRARY NAMES brotlicommon) find_library(BROTLICOMMON_LIBRARY NAMES brotlicommon)
find_library(BROTLIDEC_LIBRARY NAMES brotlidec) find_library(BROTLIDEC_LIBRARY NAMES brotlidec)
find_package_handle_standard_args(BROTLI find_package_handle_standard_args(Brotli
FOUND_VAR FOUND_VAR
BROTLI_FOUND BROTLI_FOUND
REQUIRED_VARS REQUIRED_VARS
@ -13,7 +36,7 @@ find_package_handle_standard_args(BROTLI
BROTLICOMMON_LIBRARY BROTLICOMMON_LIBRARY
BROTLI_INCLUDE_DIR BROTLI_INCLUDE_DIR
FAIL_MESSAGE FAIL_MESSAGE
"Could NOT find BROTLI" "Could NOT find Brotli"
) )
set(BROTLI_INCLUDE_DIRS ${BROTLI_INCLUDE_DIR}) set(BROTLI_INCLUDE_DIRS ${BROTLI_INCLUDE_DIR})

View file

@ -1,3 +1,26 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
# - Find c-ares # - Find c-ares
# Find the c-ares includes and library # Find the c-ares includes and library
# This module defines # This module defines
@ -7,34 +30,16 @@
# also defined, but not for general use are # also defined, but not for general use are
# CARES_LIBRARY, where to find the c-ares library. # CARES_LIBRARY, where to find the c-ares library.
find_path(CARES_INCLUDE_DIR ares.h find_path(CARES_INCLUDE_DIR ares.h)
/usr/local/include
/usr/include
)
set(CARES_NAMES ${CARES_NAMES} cares) set(CARES_NAMES ${CARES_NAMES} cares)
find_library(CARES_LIBRARY find_library(CARES_LIBRARY
NAMES ${CARES_NAMES} NAMES ${CARES_NAMES}
PATHS /usr/lib /usr/local/lib
) )
if(CARES_LIBRARY AND CARES_INCLUDE_DIR) include(FindPackageHandleStandardArgs)
set(CARES_LIBRARIES ${CARES_LIBRARY}) find_package_handle_standard_args(CARES
set(CARES_FOUND "YES") REQUIRED_VARS CARES_LIBRARY CARES_INCLUDE_DIR)
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()
mark_as_advanced( mark_as_advanced(
CARES_LIBRARY CARES_LIBRARY

View file

@ -1,3 +1,26 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
# - Try to find the GSS Kerberos library # - Try to find the GSS Kerberos library
# Once done this will define # Once done this will define
# #
@ -62,6 +85,7 @@ if(NOT _GSS_FOUND) #not found by pkg-config. Let's take more traditional approac
COMMAND ${_GSS_CONFIGURE_SCRIPT} "--cflags" "gssapi" COMMAND ${_GSS_CONFIGURE_SCRIPT} "--cflags" "gssapi"
OUTPUT_VARIABLE _GSS_CFLAGS OUTPUT_VARIABLE _GSS_CFLAGS
RESULT_VARIABLE _GSS_CONFIGURE_FAILED RESULT_VARIABLE _GSS_CONFIGURE_FAILED
OUTPUT_STRIP_TRAILING_WHITESPACE
) )
message(STATUS "CFLAGS: ${_GSS_CFLAGS}") message(STATUS "CFLAGS: ${_GSS_CFLAGS}")
if(NOT _GSS_CONFIGURE_FAILED) # 0 means success if(NOT _GSS_CONFIGURE_FAILED) # 0 means success
@ -84,6 +108,7 @@ if(NOT _GSS_FOUND) #not found by pkg-config. Let's take more traditional approac
COMMAND ${_GSS_CONFIGURE_SCRIPT} "--libs" "gssapi" COMMAND ${_GSS_CONFIGURE_SCRIPT} "--libs" "gssapi"
OUTPUT_VARIABLE _GSS_LIB_FLAGS OUTPUT_VARIABLE _GSS_LIB_FLAGS
RESULT_VARIABLE _GSS_CONFIGURE_FAILED RESULT_VARIABLE _GSS_CONFIGURE_FAILED
OUTPUT_STRIP_TRAILING_WHITESPACE
) )
message(STATUS "LDFLAGS: ${_GSS_LIB_FLAGS}") message(STATUS "LDFLAGS: ${_GSS_LIB_FLAGS}")
@ -110,6 +135,7 @@ if(NOT _GSS_FOUND) #not found by pkg-config. Let's take more traditional approac
COMMAND ${_GSS_CONFIGURE_SCRIPT} "--version" COMMAND ${_GSS_CONFIGURE_SCRIPT} "--version"
OUTPUT_VARIABLE _GSS_VERSION OUTPUT_VARIABLE _GSS_VERSION
RESULT_VARIABLE _GSS_CONFIGURE_FAILED RESULT_VARIABLE _GSS_CONFIGURE_FAILED
OUTPUT_STRIP_TRAILING_WHITESPACE
) )
# older versions may not have the "--version" parameter. In this case we just don't care. # older versions may not have the "--version" parameter. In this case we just don't care.
@ -121,6 +147,7 @@ if(NOT _GSS_FOUND) #not found by pkg-config. Let's take more traditional approac
COMMAND ${_GSS_CONFIGURE_SCRIPT} "--vendor" COMMAND ${_GSS_CONFIGURE_SCRIPT} "--vendor"
OUTPUT_VARIABLE _GSS_VENDOR OUTPUT_VARIABLE _GSS_VENDOR
RESULT_VARIABLE _GSS_CONFIGURE_FAILED 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. # older versions may not have the "--vendor" parameter. In this case we just don't care.
@ -134,7 +161,7 @@ if(NOT _GSS_FOUND) #not found by pkg-config. Let's take more traditional approac
endif() endif()
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 find_path(_GSS_INCLUDE_DIR
NAMES NAMES
@ -154,17 +181,17 @@ if(NOT _GSS_FOUND) #not found by pkg-config. Let's take more traditional approac
set(GSS_FLAVOUR "MIT") set(GSS_FLAVOUR "MIT")
else() else()
# prevent compiling the header - just check if we can include it # prevent compiling the header - just check if we can include it
set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D__ROKEN_H__") list(APPEND CMAKE_REQUIRED_DEFINITIONS -D__ROKEN_H__)
check_include_file( "roken.h" _GSS_HAVE_ROKEN_H) check_include_file( "roken.h" _GSS_HAVE_ROKEN_H)
check_include_file( "heimdal/roken.h" _GSS_HAVE_HEIMDAL_ROKEN_H) check_include_file( "heimdal/roken.h" _GSS_HAVE_HEIMDAL_ROKEN_H)
if(_GSS_HAVE_ROKEN_H OR _GSS_HAVE_HEIMDAL_ROKEN_H) if(_GSS_HAVE_ROKEN_H OR _GSS_HAVE_HEIMDAL_ROKEN_H)
set(GSS_FLAVOUR "Heimdal") set(GSS_FLAVOUR "Heimdal")
endif() endif()
set(CMAKE_REQUIRED_DEFINITIONS "") list(REMOVE_ITEM CMAKE_REQUIRED_DEFINITIONS -D__ROKEN_H__)
endif() endif()
else() 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 find_path(_GSS_INCLUDE_DIR
NAMES NAMES
"gssapi.h" "gssapi.h"

View file

@ -0,0 +1,45 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
# - Try to find the libpsl library
# Once done this will define
#
# LIBPSL_FOUND - system has the libpsl library
# LIBPSL_INCLUDE_DIR - the libpsl include directory
# LIBPSL_LIBRARY - the libpsl library name
find_path(LIBPSL_INCLUDE_DIR libpsl.h)
find_library(LIBPSL_LIBRARY NAMES psl libpsl)
if(LIBPSL_INCLUDE_DIR)
file(STRINGS "${LIBPSL_INCLUDE_DIR}/libpsl.h" libpsl_version_str REGEX "^#define[\t ]+PSL_VERSION[\t ]+\"(.*)\"")
string(REGEX REPLACE "^.*\"([^\"]+)\"" "\\1" LIBPSL_VERSION "${libpsl_version_str}")
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(LibPSL
REQUIRED_VARS LIBPSL_LIBRARY LIBPSL_INCLUDE_DIR
VERSION_VAR LIBPSL_VERSION)
mark_as_advanced(LIBPSL_INCLUDE_DIR LIBPSL_LIBRARY)

View file

@ -1,3 +1,26 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
# - Try to find the libssh2 library # - Try to find the libssh2 library
# Once done this will define # Once done this will define
# #
@ -5,31 +28,18 @@
# LIBSSH2_INCLUDE_DIR - the libssh2 include directory # LIBSSH2_INCLUDE_DIR - the libssh2 include directory
# LIBSSH2_LIBRARY - the libssh2 library name # LIBSSH2_LIBRARY - the libssh2 library name
if(LIBSSH2_INCLUDE_DIR AND LIBSSH2_LIBRARY) find_path(LIBSSH2_INCLUDE_DIR libssh2.h)
set(LibSSH2_FIND_QUIETLY TRUE)
endif()
find_path(LIBSSH2_INCLUDE_DIR libssh2.h find_library(LIBSSH2_LIBRARY NAMES ssh2 libssh2)
)
find_library(LIBSSH2_LIBRARY NAMES ssh2
)
if(LIBSSH2_INCLUDE_DIR) 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].*") 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}")
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}")
endif() endif()
include(FindPackageHandleStandardArgs) 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)

View file

@ -0,0 +1,70 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
#[=======================================================================[.rst:
FindMSH3
----------
Find the msh3 library
Result Variables
^^^^^^^^^^^^^^^^
``MSH3_FOUND``
System has msh3
``MSH3_INCLUDE_DIRS``
The msh3 include directories.
``MSH3_LIBRARIES``
The libraries needed to use msh3
#]=======================================================================]
if(UNIX)
find_package(PkgConfig QUIET)
pkg_search_module(PC_MSH3 libmsh3)
endif()
find_path(MSH3_INCLUDE_DIR msh3.h
HINTS
${PC_MSH3_INCLUDEDIR}
${PC_MSH3_INCLUDE_DIRS}
)
find_library(MSH3_LIBRARY NAMES msh3
HINTS
${PC_MSH3_LIBDIR}
${PC_MSH3_LIBRARY_DIRS}
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(MSH3
REQUIRED_VARS
MSH3_LIBRARY
MSH3_INCLUDE_DIR
)
if(MSH3_FOUND)
set(MSH3_LIBRARIES ${MSH3_LIBRARY})
set(MSH3_INCLUDE_DIRS ${MSH3_INCLUDE_DIR})
endif()
mark_as_advanced(MSH3_INCLUDE_DIRS MSH3_LIBRARIES)

View file

@ -1,3 +1,26 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
find_path(MBEDTLS_INCLUDE_DIRS mbedtls/ssl.h) find_path(MBEDTLS_INCLUDE_DIRS mbedtls/ssl.h)
find_library(MBEDTLS_LIBRARY mbedtls) find_library(MBEDTLS_LIBRARY mbedtls)
@ -7,7 +30,7 @@ find_library(MBEDCRYPTO_LIBRARY mbedcrypto)
set(MBEDTLS_LIBRARIES "${MBEDTLS_LIBRARY}" "${MBEDX509_LIBRARY}" "${MBEDCRYPTO_LIBRARY}") set(MBEDTLS_LIBRARIES "${MBEDTLS_LIBRARY}" "${MBEDX509_LIBRARY}" "${MBEDCRYPTO_LIBRARY}")
include(FindPackageHandleStandardArgs) include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(MBEDTLS DEFAULT_MSG find_package_handle_standard_args(MbedTLS DEFAULT_MSG
MBEDTLS_INCLUDE_DIRS MBEDTLS_LIBRARY MBEDX509_LIBRARY MBEDCRYPTO_LIBRARY) MBEDTLS_INCLUDE_DIRS MBEDTLS_LIBRARY MBEDX509_LIBRARY MBEDCRYPTO_LIBRARY)
mark_as_advanced(MBEDTLS_INCLUDE_DIRS MBEDTLS_LIBRARY MBEDX509_LIBRARY MBEDCRYPTO_LIBRARY) mark_as_advanced(MBEDTLS_INCLUDE_DIRS MBEDTLS_LIBRARY MBEDX509_LIBRARY MBEDCRYPTO_LIBRARY)

View file

@ -1,3 +1,26 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
include(FindPackageHandleStandardArgs) include(FindPackageHandleStandardArgs)
find_path(NGHTTP2_INCLUDE_DIR "nghttp2/nghttp2.h") find_path(NGHTTP2_INCLUDE_DIR "nghttp2/nghttp2.h")
@ -10,9 +33,9 @@ find_package_handle_standard_args(NGHTTP2
REQUIRED_VARS REQUIRED_VARS
NGHTTP2_LIBRARY NGHTTP2_LIBRARY
NGHTTP2_INCLUDE_DIR NGHTTP2_INCLUDE_DIR
FAIL_MESSAGE
"Could NOT find NGHTTP2"
) )
set(NGHTTP2_INCLUDE_DIRS ${NGHTTP2_INCLUDE_DIR}) set(NGHTTP2_INCLUDE_DIRS ${NGHTTP2_INCLUDE_DIR})
set(NGHTTP2_LIBRARIES ${NGHTTP2_LIBRARY}) set(NGHTTP2_LIBRARIES ${NGHTTP2_LIBRARY})
mark_as_advanced(NGHTTP2_INCLUDE_DIRS NGHTTP2_LIBRARIES)

View file

@ -0,0 +1,78 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
#[=======================================================================[.rst:
FindNGHTTP3
----------
Find the nghttp3 library
Result Variables
^^^^^^^^^^^^^^^^
``NGHTTP3_FOUND``
System has nghttp3
``NGHTTP3_INCLUDE_DIRS``
The nghttp3 include directories.
``NGHTTP3_LIBRARIES``
The libraries needed to use nghttp3
``NGHTTP3_VERSION``
version of nghttp3.
#]=======================================================================]
if(UNIX)
find_package(PkgConfig QUIET)
pkg_search_module(PC_NGHTTP3 libnghttp3)
endif()
find_path(NGHTTP3_INCLUDE_DIR nghttp3/nghttp3.h
HINTS
${PC_NGHTTP3_INCLUDEDIR}
${PC_NGHTTP3_INCLUDE_DIRS}
)
find_library(NGHTTP3_LIBRARY NAMES nghttp3
HINTS
${PC_NGHTTP3_LIBDIR}
${PC_NGHTTP3_LIBRARY_DIRS}
)
if(PC_NGHTTP3_VERSION)
set(NGHTTP3_VERSION ${PC_NGHTTP3_VERSION})
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(NGHTTP3
REQUIRED_VARS
NGHTTP3_LIBRARY
NGHTTP3_INCLUDE_DIR
VERSION_VAR NGHTTP3_VERSION
)
if(NGHTTP3_FOUND)
set(NGHTTP3_LIBRARIES ${NGHTTP3_LIBRARY})
set(NGHTTP3_INCLUDE_DIRS ${NGHTTP3_INCLUDE_DIR})
endif()
mark_as_advanced(NGHTTP3_INCLUDE_DIRS NGHTTP3_LIBRARIES)

View file

@ -0,0 +1,115 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
#[=======================================================================[.rst:
FindNGTCP2
----------
Find the ngtcp2 library
This module accepts optional COMPONENTS to control the crypto library (these are
mutually exclusive)::
OpenSSL: Use libngtcp2_crypto_openssl
GnuTLS: Use libngtcp2_crypto_gnutls
Result Variables
^^^^^^^^^^^^^^^^
``NGTCP2_FOUND``
System has ngtcp2
``NGTCP2_INCLUDE_DIRS``
The ngtcp2 include directories.
``NGTCP2_LIBRARIES``
The libraries needed to use ngtcp2
``NGTCP2_VERSION``
version of ngtcp2.
#]=======================================================================]
if(UNIX)
find_package(PkgConfig QUIET)
pkg_search_module(PC_NGTCP2 libngtcp2)
endif()
find_path(NGTCP2_INCLUDE_DIR ngtcp2/ngtcp2.h
HINTS
${PC_NGTCP2_INCLUDEDIR}
${PC_NGTCP2_INCLUDE_DIRS}
)
find_library(NGTCP2_LIBRARY NAMES ngtcp2
HINTS
${PC_NGTCP2_LIBDIR}
${PC_NGTCP2_LIBRARY_DIRS}
)
if(PC_NGTCP2_VERSION)
set(NGTCP2_VERSION ${PC_NGTCP2_VERSION})
endif()
if(NGTCP2_FIND_COMPONENTS)
set(NGTCP2_CRYPTO_BACKEND "")
foreach(component IN LISTS NGTCP2_FIND_COMPONENTS)
if(component MATCHES "^(BoringSSL|OpenSSL|wolfSSL|GnuTLS)")
if(NGTCP2_CRYPTO_BACKEND)
message(FATAL_ERROR "NGTCP2: Only one crypto library can be selected")
endif()
set(NGTCP2_CRYPTO_BACKEND ${component})
endif()
endforeach()
if(NGTCP2_CRYPTO_BACKEND)
string(TOLOWER "ngtcp2_crypto_${NGTCP2_CRYPTO_BACKEND}" _crypto_library)
if(UNIX)
pkg_search_module(PC_${_crypto_library} lib${_crypto_library})
endif()
find_library(${_crypto_library}_LIBRARY
NAMES
${_crypto_library}
HINTS
${PC_${_crypto_library}_LIBDIR}
${PC_${_crypto_library}_LIBRARY_DIRS}
)
if(${_crypto_library}_LIBRARY)
set(NGTCP2_${NGTCP2_CRYPTO_BACKEND}_FOUND TRUE)
set(NGTCP2_CRYPTO_LIBRARY ${${_crypto_library}_LIBRARY})
endif()
endif()
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(NGTCP2
REQUIRED_VARS
NGTCP2_LIBRARY
NGTCP2_INCLUDE_DIR
VERSION_VAR NGTCP2_VERSION
HANDLE_COMPONENTS
)
if(NGTCP2_FOUND)
set(NGTCP2_LIBRARIES ${NGTCP2_LIBRARY} ${NGTCP2_CRYPTO_LIBRARY})
set(NGTCP2_INCLUDE_DIRS ${NGTCP2_INCLUDE_DIR})
endif()
mark_as_advanced(NGTCP2_INCLUDE_DIRS NGTCP2_LIBRARIES)

View file

@ -0,0 +1,40 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
if(UNIX)
find_package(PkgConfig QUIET)
pkg_search_module(PC_NSS nss)
endif()
if(NOT PC_NSS_FOUND)
return()
endif()
set(NSS_LIBRARIES ${PC_NSS_LINK_LIBRARIES})
set(NSS_INCLUDE_DIRS ${PC_NSS_INCLUDE_DIRS})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(NSS
REQUIRED_VARS NSS_LIBRARIES NSS_INCLUDE_DIRS
VERSION_VAR PC_NSS_VERSION)
mark_as_advanced(NSS_INCLUDE_DIRS NSS_LIBRARIES)

View file

@ -0,0 +1,70 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
#[=======================================================================[.rst:
FindQUICHE
----------
Find the quiche library
Result Variables
^^^^^^^^^^^^^^^^
``QUICHE_FOUND``
System has quiche
``QUICHE_INCLUDE_DIRS``
The quiche include directories.
``QUICHE_LIBRARIES``
The libraries needed to use quiche
#]=======================================================================]
if(UNIX)
find_package(PkgConfig QUIET)
pkg_search_module(PC_QUICHE quiche)
endif()
find_path(QUICHE_INCLUDE_DIR quiche.h
HINTS
${PC_QUICHE_INCLUDEDIR}
${PC_QUICHE_INCLUDE_DIRS}
)
find_library(QUICHE_LIBRARY NAMES quiche
HINTS
${PC_QUICHE_LIBDIR}
${PC_QUICHE_LIBRARY_DIRS}
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(QUICHE
REQUIRED_VARS
QUICHE_LIBRARY
QUICHE_INCLUDE_DIR
)
if(QUICHE_FOUND)
set(QUICHE_LIBRARIES ${QUICHE_LIBRARY})
set(QUICHE_INCLUDE_DIRS ${QUICHE_INCLUDE_DIR})
endif()
mark_as_advanced(QUICHE_INCLUDE_DIRS QUICHE_LIBRARIES)

View file

@ -0,0 +1,36 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
find_path(WolfSSL_INCLUDE_DIR NAMES wolfssl/ssl.h)
find_library(WolfSSL_LIBRARY NAMES wolfssl)
mark_as_advanced(WolfSSL_INCLUDE_DIR WolfSSL_LIBRARY)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(WolfSSL
REQUIRED_VARS WolfSSL_INCLUDE_DIR WolfSSL_LIBRARY
)
if(WolfSSL_FOUND)
set(WolfSSL_INCLUDE_DIRS ${WolfSSL_INCLUDE_DIR})
set(WolfSSL_LIBRARIES ${WolfSSL_LIBRARY})
endif()

View file

@ -0,0 +1,71 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
#[=======================================================================[.rst:
FindZstd
----------
Find the zstd library
Result Variables
^^^^^^^^^^^^^^^^
``Zstd_FOUND``
System has zstd
``Zstd_INCLUDE_DIRS``
The zstd include directories.
``Zstd_LIBRARIES``
The libraries needed to use zstd
#]=======================================================================]
if(UNIX)
find_package(PkgConfig QUIET)
pkg_search_module(PC_Zstd libzstd)
endif()
find_path(Zstd_INCLUDE_DIR zstd.h
HINTS
${PC_Zstd_INCLUDEDIR}
${PC_Zstd_INCLUDE_DIRS}
)
find_library(Zstd_LIBRARY NAMES zstd
HINTS
${PC_Zstd_LIBDIR}
${PC_Zstd_LIBRARY_DIRS}
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Zstd
REQUIRED_VARS
Zstd_LIBRARY
Zstd_INCLUDE_DIR
)
if(Zstd_FOUND)
set(Zstd_LIBRARIES ${Zstd_LIBRARY})
set(Zstd_INCLUDE_DIRS ${Zstd_INCLUDE_DIR})
endif()
mark_as_advanced(Zstd_INCLUDE_DIRS Zstd_LIBRARIES)

View file

@ -1,3 +1,26 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
#File defines convenience macros for available feature testing #File defines convenience macros for available feature testing
# This macro checks if the symbol exists in the library and if it # This macro checks if the symbol exists in the library and if it
@ -86,3 +109,14 @@ macro(curl_nroff_check)
message(WARNING "Found no *nroff program") message(WARNING "Found no *nroff program")
endif() endif()
endmacro() endmacro()
macro(optional_dependency DEPENDENCY)
set(CURL_${DEPENDENCY} AUTO CACHE STRING "Build curl with ${DEPENDENCY} support (AUTO, ON or OFF)")
set_property(CACHE CURL_${DEPENDENCY} PROPERTY STRINGS AUTO ON OFF)
if(CURL_${DEPENDENCY} STREQUAL AUTO)
find_package(${DEPENDENCY})
elseif(CURL_${DEPENDENCY})
find_package(${DEPENDENCY} REQUIRED)
endif()
endmacro()

View file

@ -1,3 +1,26 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
include(CheckCSourceCompiles) include(CheckCSourceCompiles)
# The begin of the sources (macros and includes) # The begin of the sources (macros and includes)
set(_source_epilogue "#undef inline") set(_source_epilogue "#undef inline")
@ -12,7 +35,6 @@ set(signature_call_conv)
if(HAVE_WINDOWS_H) if(HAVE_WINDOWS_H)
add_header_include(HAVE_WINSOCK2_H "winsock2.h") add_header_include(HAVE_WINSOCK2_H "winsock2.h")
add_header_include(HAVE_WINDOWS_H "windows.h") add_header_include(HAVE_WINDOWS_H "windows.h")
add_header_include(HAVE_WINSOCK_H "winsock.h")
set(_source_epilogue set(_source_epilogue
"${_source_epilogue}\n#ifndef WIN32_LEAN_AND_MEAN\n#define WIN32_LEAN_AND_MEAN\n#endif") "${_source_epilogue}\n#ifndef WIN32_LEAN_AND_MEAN\n#define WIN32_LEAN_AND_MEAN\n#endif")
set(signature_call_conv "PASCAL") set(signature_call_conv "PASCAL")
@ -26,138 +48,6 @@ endif()
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
check_c_source_compiles("${_source_epilogue}
int main(void) {
recv(0, 0, 0, 0);
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")
foreach(recv_retv "int" "ssize_t" )
foreach(recv_arg1 "SOCKET" "int" )
foreach(recv_arg2 "char *" "void *" )
foreach(recv_arg3 "int" "size_t" "socklen_t" "unsigned int")
foreach(recv_arg4 "int" "unsigned int")
if(NOT curl_cv_func_recv_done)
unset(curl_cv_func_recv_test CACHE)
check_c_source_compiles("
${_source_epilogue}
extern ${recv_retv} ${signature_call_conv}
recv(${recv_arg1}, ${recv_arg2}, ${recv_arg3}, ${recv_arg4});
int main(void) {
${recv_arg1} s=0;
${recv_arg2} buf=0;
${recv_arg3} len=0;
${recv_arg4} flags=0;
${recv_retv} res = recv(s, buf, len, flags);
(void) res;
return 0;
}"
curl_cv_func_recv_test)
message(STATUS
"Tested: ${recv_retv} recv(${recv_arg1}, ${recv_arg2}, ${recv_arg3}, ${recv_arg4})")
if(curl_cv_func_recv_test)
set(curl_cv_func_recv_args
"${recv_arg1},${recv_arg2},${recv_arg3},${recv_arg4},${recv_retv}")
set(RECV_TYPE_ARG1 "${recv_arg1}")
set(RECV_TYPE_ARG2 "${recv_arg2}")
set(RECV_TYPE_ARG3 "${recv_arg3}")
set(RECV_TYPE_ARG4 "${recv_arg4}")
set(RECV_TYPE_RETV "${recv_retv}")
set(HAVE_RECV 1)
set(curl_cv_func_recv_done 1)
endif()
endif()
endforeach()
endforeach()
endforeach()
endforeach()
endforeach()
else()
string(REGEX REPLACE "^([^,]*),[^,]*,[^,]*,[^,]*,[^,]*$" "\\1" RECV_TYPE_ARG1 "${curl_cv_func_recv_args}")
string(REGEX REPLACE "^[^,]*,([^,]*),[^,]*,[^,]*,[^,]*$" "\\1" RECV_TYPE_ARG2 "${curl_cv_func_recv_args}")
string(REGEX REPLACE "^[^,]*,[^,]*,([^,]*),[^,]*,[^,]*$" "\\1" RECV_TYPE_ARG3 "${curl_cv_func_recv_args}")
string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,([^,]*),[^,]*$" "\\1" RECV_TYPE_ARG4 "${curl_cv_func_recv_args}")
string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,[^,]*,([^,]*)$" "\\1" RECV_TYPE_RETV "${curl_cv_func_recv_args}")
endif()
if("${curl_cv_func_recv_args}" STREQUAL "unknown")
message(FATAL_ERROR "Cannot find proper types to use for recv args")
endif()
else()
message(FATAL_ERROR "Unable to link function recv")
endif()
set(curl_cv_func_recv_args "${curl_cv_func_recv_args}" CACHE INTERNAL "Arguments for recv")
set(HAVE_RECV 1)
check_c_source_compiles("${_source_epilogue}
int main(void) {
send(0, 0, 0, 0);
return 0;
}" curl_cv_send)
if(curl_cv_send)
if(NOT DEFINED curl_cv_func_send_args OR "${curl_cv_func_send_args}" STREQUAL "unknown")
foreach(send_retv "int" "ssize_t" )
foreach(send_arg1 "SOCKET" "int" "ssize_t" )
foreach(send_arg2 "const char *" "const void *" "void *" "char *")
foreach(send_arg3 "int" "size_t" "socklen_t" "unsigned int")
foreach(send_arg4 "int" "unsigned int")
if(NOT curl_cv_func_send_done)
unset(curl_cv_func_send_test CACHE)
check_c_source_compiles("
${_source_epilogue}
extern ${send_retv} ${signature_call_conv}
send(${send_arg1}, ${send_arg2}, ${send_arg3}, ${send_arg4});
int main(void) {
${send_arg1} s=0;
${send_arg2} buf=0;
${send_arg3} len=0;
${send_arg4} flags=0;
${send_retv} res = send(s, buf, len, flags);
(void) res;
return 0;
}"
curl_cv_func_send_test)
message(STATUS
"Tested: ${send_retv} send(${send_arg1}, ${send_arg2}, ${send_arg3}, ${send_arg4})")
if(curl_cv_func_send_test)
string(REGEX REPLACE "(const) .*" "\\1" send_qual_arg2 "${send_arg2}")
string(REGEX REPLACE "const (.*)" "\\1" send_arg2 "${send_arg2}")
set(curl_cv_func_send_args
"${send_arg1},${send_arg2},${send_arg3},${send_arg4},${send_retv},${send_qual_arg2}")
set(SEND_TYPE_ARG1 "${send_arg1}")
set(SEND_TYPE_ARG2 "${send_arg2}")
set(SEND_TYPE_ARG3 "${send_arg3}")
set(SEND_TYPE_ARG4 "${send_arg4}")
set(SEND_TYPE_RETV "${send_retv}")
set(HAVE_SEND 1)
set(curl_cv_func_send_done 1)
endif()
endif()
endforeach()
endforeach()
endforeach()
endforeach()
endforeach()
else()
string(REGEX REPLACE "^([^,]*),[^,]*,[^,]*,[^,]*,[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG1 "${curl_cv_func_send_args}")
string(REGEX REPLACE "^[^,]*,([^,]*),[^,]*,[^,]*,[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG2 "${curl_cv_func_send_args}")
string(REGEX REPLACE "^[^,]*,[^,]*,([^,]*),[^,]*,[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG3 "${curl_cv_func_send_args}")
string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,([^,]*),[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG4 "${curl_cv_func_send_args}")
string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,[^,]*,([^,]*),[^,]*$" "\\1" SEND_TYPE_RETV "${curl_cv_func_send_args}")
string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,([^,]*)$" "\\1" SEND_QUAL_ARG2 "${curl_cv_func_send_args}")
endif()
if("${curl_cv_func_send_args}" STREQUAL "unknown")
message(FATAL_ERROR "Cannot find proper types to use for send args")
endif()
set(SEND_QUAL_ARG2 "const")
else()
message(FATAL_ERROR "Unable to link function send")
endif()
set(curl_cv_func_send_args "${curl_cv_func_send_args}" CACHE INTERNAL "Arguments for send")
set(HAVE_SEND 1)
check_c_source_compiles("${_source_epilogue} check_c_source_compiles("${_source_epilogue}
int main(void) { int main(void) {
int flag = MSG_NOSIGNAL; int flag = MSG_NOSIGNAL;
@ -179,28 +69,6 @@ int main(void) {
return 0; return 0;
}" HAVE_STRUCT_TIMEVAL) }" HAVE_STRUCT_TIMEVAL)
set(HAVE_SIG_ATOMIC_T 1)
set(CMAKE_REQUIRED_FLAGS)
if(HAVE_SIGNAL_H)
set(CMAKE_REQUIRED_FLAGS "-DHAVE_SIGNAL_H")
set(CMAKE_EXTRA_INCLUDE_FILES "signal.h")
endif()
check_type_size("sig_atomic_t" SIZEOF_SIG_ATOMIC_T)
if(HAVE_SIZEOF_SIG_ATOMIC_T)
check_c_source_compiles("
#ifdef HAVE_SIGNAL_H
# include <signal.h>
#endif
int main(void) {
static volatile sig_atomic_t dummy = 0;
(void)dummy;
return 0;
}" HAVE_SIG_ATOMIC_T_NOT_VOLATILE)
if(NOT HAVE_SIG_ATOMIC_T_NOT_VOLATILE)
set(HAVE_SIG_ATOMIC_T_VOLATILE 1)
endif()
endif()
if(HAVE_WINDOWS_H) if(HAVE_WINDOWS_H)
set(CMAKE_EXTRA_INCLUDE_FILES winsock2.h) set(CMAKE_EXTRA_INCLUDE_FILES winsock2.h)
else() else()
@ -217,48 +85,52 @@ endif()
unset(CMAKE_TRY_COMPILE_TARGET_TYPE) unset(CMAKE_TRY_COMPILE_TARGET_TYPE)
if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) if(NOT CMAKE_CROSSCOMPILING)
# if not cross-compilation... if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "iOS")
include(CheckCSourceRuns) # only try this on non-apple platforms
set(CMAKE_REQUIRED_FLAGS "")
if(HAVE_SYS_POLL_H)
set(CMAKE_REQUIRED_FLAGS "-DHAVE_SYS_POLL_H")
elseif(HAVE_POLL_H)
set(CMAKE_REQUIRED_FLAGS "-DHAVE_POLL_H")
endif()
check_c_source_runs("
#include <stdlib.h>
#include <sys/time.h>
#ifdef HAVE_SYS_POLL_H # if not cross-compilation...
# include <sys/poll.h> include(CheckCSourceRuns)
#elif HAVE_POLL_H set(CMAKE_REQUIRED_FLAGS "")
# include <poll.h> if(HAVE_SYS_POLL_H)
#endif set(CMAKE_REQUIRED_FLAGS "-DHAVE_SYS_POLL_H")
elseif(HAVE_POLL_H)
set(CMAKE_REQUIRED_FLAGS "-DHAVE_POLL_H")
endif()
check_c_source_runs("
#include <stdlib.h>
#include <sys/time.h>
int main(void) #ifdef HAVE_SYS_POLL_H
{ # include <sys/poll.h>
if(0 != poll(0, 0, 10)) { #elif HAVE_POLL_H
return 1; /* fail */ # include <poll.h>
} #endif
else {
/* detect the 10.12 poll() breakage */
struct timeval before, after;
int rc;
size_t us;
gettimeofday(&before, NULL); int main(void)
rc = poll(NULL, 0, 500); {
gettimeofday(&after, NULL); if(0 != poll(0, 0, 10)) {
return 1; /* fail */
us = (after.tv_sec - before.tv_sec) * 1000000 +
(after.tv_usec - before.tv_usec);
if(us < 400000) {
return 1;
} }
} else {
return 0; /* detect the 10.12 poll() breakage */
struct timeval before, after;
int rc;
size_t us;
gettimeofday(&before, NULL);
rc = poll(NULL, 0, 500);
gettimeofday(&after, NULL);
us = (after.tv_sec - before.tv_sec) * 1000000 +
(after.tv_usec - before.tv_usec);
if(us < 400000) {
return 1;
}
}
return 0;
}" HAVE_POLL_FINE) }" HAVE_POLL_FINE)
endif()
endif() endif()

View file

@ -1,35 +1,41 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
if(NOT UNIX) if(NOT UNIX)
if(WIN32) if(WIN32)
set(HAVE_LIBDL 0)
set(HAVE_LIBUCB 0)
set(HAVE_LIBSOCKET 0) set(HAVE_LIBSOCKET 0)
set(NOT_NEED_LIBNSL 0)
set(HAVE_LIBNSL 0)
set(HAVE_GETHOSTNAME 1) set(HAVE_GETHOSTNAME 1)
set(HAVE_LIBZ 0) set(HAVE_LIBZ 0)
set(HAVE_LIBCRYPTO 0)
set(HAVE_DLOPEN 0)
set(HAVE_ALLOCA_H 0)
set(HAVE_ARPA_INET_H 0) set(HAVE_ARPA_INET_H 0)
set(HAVE_DLFCN_H 0)
set(HAVE_FCNTL_H 1) set(HAVE_FCNTL_H 1)
set(HAVE_INTTYPES_H 0)
set(HAVE_IO_H 1) set(HAVE_IO_H 1)
set(HAVE_MALLOC_H 1)
set(HAVE_MEMORY_H 1)
set(HAVE_NETDB_H 0) set(HAVE_NETDB_H 0)
set(HAVE_NETINET_IF_ETHER_H 0)
set(HAVE_NETINET_IN_H 0) set(HAVE_NETINET_IN_H 0)
set(HAVE_NET_IF_H 0) set(HAVE_NET_IF_H 0)
set(HAVE_PROCESS_H 1)
set(HAVE_PWD_H 0) set(HAVE_PWD_H 0)
set(HAVE_SETJMP_H 1) set(HAVE_SETJMP_H 1)
set(HAVE_SGTTY_H 0)
set(HAVE_SIGNAL_H 1) set(HAVE_SIGNAL_H 1)
set(HAVE_SOCKIO_H 0)
set(HAVE_STDINT_H 0)
set(HAVE_STDLIB_H 1) set(HAVE_STDLIB_H 1)
set(HAVE_STRINGS_H 0) set(HAVE_STRINGS_H 0)
set(HAVE_STRING_H 1) set(HAVE_STRING_H 1)
@ -45,54 +51,26 @@ if(NOT UNIX)
set(HAVE_TERMIOS_H 0) set(HAVE_TERMIOS_H 0)
set(HAVE_TERMIO_H 0) set(HAVE_TERMIO_H 0)
set(HAVE_TIME_H 1) set(HAVE_TIME_H 1)
set(HAVE_UNISTD_H 0)
set(HAVE_UTIME_H 0) set(HAVE_UTIME_H 0)
set(HAVE_X509_H 0)
set(HAVE_ZLIB_H 0)
set(HAVE_SOCKET 1) set(HAVE_SOCKET 1)
set(HAVE_POLL 0)
set(HAVE_SELECT 1) set(HAVE_SELECT 1)
set(HAVE_STRDUP 1) set(HAVE_STRDUP 1)
set(HAVE_STRSTR 1)
set(HAVE_STRTOK_R 0)
set(HAVE_STRFTIME 1)
set(HAVE_UNAME 0)
set(HAVE_STRCASECMP 0)
set(HAVE_STRICMP 1) set(HAVE_STRICMP 1)
set(HAVE_STRCMPI 1) set(HAVE_STRCMPI 1)
set(HAVE_GETHOSTBYADDR 1)
set(HAVE_GETTIMEOFDAY 0) set(HAVE_GETTIMEOFDAY 0)
set(HAVE_INET_ADDR 1)
set(HAVE_INET_NTOA 1)
set(HAVE_INET_NTOA_R 0)
set(HAVE_TCGETATTR 0)
set(HAVE_TCSETATTR 0)
set(HAVE_PERROR 1)
set(HAVE_CLOSESOCKET 1) set(HAVE_CLOSESOCKET 1)
set(HAVE_SETVBUF 0)
set(HAVE_SIGSETJMP 0) set(HAVE_SIGSETJMP 0)
set(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1)
set(HAVE_GETPASS_R 0) set(HAVE_GETPASS_R 0)
set(HAVE_STRLCAT 0)
set(HAVE_GETPWUID 0) set(HAVE_GETPWUID 0)
set(HAVE_GETEUID 0) set(HAVE_GETEUID 0)
set(HAVE_UTIME 1) set(HAVE_UTIME 1)
set(HAVE_RAND_EGD 0) set(HAVE_RAND_EGD 0)
set(HAVE_RAND_SCREEN 0)
set(HAVE_RAND_STATUS 0)
set(HAVE_GMTIME_R 0) set(HAVE_GMTIME_R 0)
set(HAVE_LOCALTIME_R 0)
set(HAVE_GETHOSTBYADDR_R 0)
set(HAVE_GETHOSTBYNAME_R 0) set(HAVE_GETHOSTBYNAME_R 0)
set(HAVE_SIGNAL_FUNC 1) set(HAVE_SIGNAL 1)
set(HAVE_SIGNAL_MACRO 0)
set(HAVE_GETHOSTBYADDR_R_5 0)
set(HAVE_GETHOSTBYADDR_R_5_REENTRANT 0)
set(HAVE_GETHOSTBYADDR_R_7 0)
set(HAVE_GETHOSTBYADDR_R_7_REENTRANT 0)
set(HAVE_GETHOSTBYADDR_R_8 0)
set(HAVE_GETHOSTBYADDR_R_8_REENTRANT 0)
set(HAVE_GETHOSTBYNAME_R_3 0) set(HAVE_GETHOSTBYNAME_R_3 0)
set(HAVE_GETHOSTBYNAME_R_3_REENTRANT 0) set(HAVE_GETHOSTBYNAME_R_3_REENTRANT 0)
set(HAVE_GETHOSTBYNAME_R_5 0) set(HAVE_GETHOSTBYNAME_R_5 0)
@ -103,15 +81,7 @@ if(NOT UNIX)
set(TIME_WITH_SYS_TIME 0) set(TIME_WITH_SYS_TIME 0)
set(HAVE_O_NONBLOCK 0) set(HAVE_O_NONBLOCK 0)
set(HAVE_IN_ADDR_T 0) set(HAVE_IN_ADDR_T 0)
set(HAVE_INET_NTOA_R_DECL 0)
set(HAVE_INET_NTOA_R_DECL_REENTRANT 0)
if(ENABLE_IPV6)
set(HAVE_GETADDRINFO 1)
else()
set(HAVE_GETADDRINFO 0)
endif()
set(STDC_HEADERS 1) set(STDC_HEADERS 1)
set(RETSIGTYPE_TEST 1)
set(HAVE_SIGACTION 0) set(HAVE_SIGACTION 0)
set(HAVE_MACRO_SIGSETJMP 0) set(HAVE_MACRO_SIGSETJMP 0)

View file

@ -1,13 +1,35 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
# File containing various utilities # File containing various utilities
# Returns a list of arguments that evaluate to true # Returns a list of arguments that evaluate to true
function(count_true output_count_var) function(count_true output_count_var)
set(lst) set(lst_len 0)
foreach(option_var IN LISTS ARGN) foreach(option_var IN LISTS ARGN)
if(${option_var}) if(${option_var})
list(APPEND lst ${option_var}) math(EXPR lst_len "${lst_len} + 1")
endif() endif()
endforeach() endforeach()
list(LENGTH lst lst_len)
set(${output_count_var} ${lst_len} PARENT_SCOPE) set(${output_count_var} ${lst_len} PARENT_SCOPE)
endfunction() endfunction()

View file

@ -1,3 +1,26 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
endif() endif()

View file

@ -1,3 +1,26 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
@PACKAGE_INIT@ @PACKAGE_INIT@
include(CMakeFindDependencyMacro) include(CMakeFindDependencyMacro)

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
COPYRIGHT AND PERMISSION NOTICE COPYRIGHT AND PERMISSION NOTICE
Copyright (c) 1996 - 2019, Daniel Stenberg, <daniel@haxx.se>, and many Copyright (c) 1996 - 2023, Daniel Stenberg, <daniel@haxx.se>, and many
contributors, see the THANKS file. contributors, see the THANKS file.
All rights reserved. All rights reserved.

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
#ifndef __CURL_CURLVER_H #ifndef CURLINC_CURLVER_H
#define __CURL_CURLVER_H #define CURLINC_CURLVER_H
/*************************************************************************** /***************************************************************************
* _ _ ____ _ * _ _ ____ _
* Project ___| | | | _ \| | * Project ___| | | | _ \| |
@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -20,26 +20,28 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
/* This header file contains nothing but libcurl version info, generated by /* This header file contains nothing but libcurl version info, generated by
a script at release-time. This was made its own header file in 7.11.2 */ a script at release-time. This was made its own header file in 7.11.2 */
/* This is the global package copyright */ /* This is the global package copyright */
#define LIBCURL_COPYRIGHT "1996 - 2019 Daniel Stenberg, <daniel@haxx.se>." #define LIBCURL_COPYRIGHT "Daniel Stenberg, <daniel@haxx.se>."
/* This is the version number of the libcurl package from which this header /* This is the version number of the libcurl package from which this header
file origins: */ file origins: */
#define LIBCURL_VERSION "7.65.0" #define LIBCURL_VERSION "8.0.1"
/* The numeric version number is also available "in parts" by using these /* The numeric version number is also available "in parts" by using these
defines: */ defines: */
#define LIBCURL_VERSION_MAJOR 7 #define LIBCURL_VERSION_MAJOR 8
#define LIBCURL_VERSION_MINOR 65 #define LIBCURL_VERSION_MINOR 0
#define LIBCURL_VERSION_PATCH 0 #define LIBCURL_VERSION_PATCH 1
/* This is the numeric version of the libcurl version number, meant for easier /* This is the numeric version of the libcurl version number, meant for easier
parsing and comparions by programs. The LIBCURL_VERSION_NUM define will parsing and comparisons by programs. The LIBCURL_VERSION_NUM define will
always follow this syntax: always follow this syntax:
0xXXYYZZ 0xXXYYZZ
@ -57,7 +59,7 @@
CURL_VERSION_BITS() macro since curl's own configure script greps for it CURL_VERSION_BITS() macro since curl's own configure script greps for it
and needs it to contain the full number. and needs it to contain the full number.
*/ */
#define LIBCURL_VERSION_NUM 0x074100 #define LIBCURL_VERSION_NUM 0x080001
/* /*
* This is the date and time when the full source package was created. The * This is the date and time when the full source package was created. The
@ -74,4 +76,4 @@
#define CURL_AT_LEAST_VERSION(x,y,z) \ #define CURL_AT_LEAST_VERSION(x,y,z) \
(LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z)) (LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z))
#endif /* __CURL_CURLVER_H */ #endif /* CURLINC_CURLVER_H */

View file

@ -1,5 +1,5 @@
#ifndef __CURL_EASY_H #ifndef CURLINC_EASY_H
#define __CURL_EASY_H #define CURLINC_EASY_H
/*************************************************************************** /***************************************************************************
* _ _ ____ _ * _ _ ____ _
* Project ___| | | | _ \| | * Project ___| | | | _ \| |
@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -20,11 +20,24 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* Flag bits in the curl_blob struct: */
#define CURL_BLOB_COPY 1 /* tell libcurl to copy the data */
#define CURL_BLOB_NOCOPY 0 /* tell libcurl to NOT copy the data */
struct curl_blob {
void *data;
size_t len;
unsigned int flags; /* bit 0 is defined, the rest are reserved and should be
left zeroes */
};
CURL_EXTERN CURL *curl_easy_init(void); CURL_EXTERN CURL *curl_easy_init(void);
CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...); CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
CURL_EXTERN CURLcode curl_easy_perform(CURL *curl); CURL_EXTERN CURLcode curl_easy_perform(CURL *curl);
@ -106,7 +119,7 @@ CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer,
CURL_EXTERN CURLcode curl_easy_upkeep(CURL *curl); CURL_EXTERN CURLcode curl_easy_upkeep(CURL *curl);
#ifdef __cplusplus #ifdef __cplusplus
} } /* end of extern "C" */
#endif #endif
#endif #endif

View file

@ -0,0 +1,74 @@
#ifndef CURLINC_HEADER_H
#define CURLINC_HEADER_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
struct curl_header {
char *name; /* this might not use the same case */
char *value;
size_t amount; /* number of headers using this name */
size_t index; /* ... of this instance, 0 or higher */
unsigned int origin; /* see bits below */
void *anchor; /* handle privately used by libcurl */
};
/* 'origin' bits */
#define CURLH_HEADER (1<<0) /* plain server header */
#define CURLH_TRAILER (1<<1) /* trailers */
#define CURLH_CONNECT (1<<2) /* CONNECT headers */
#define CURLH_1XX (1<<3) /* 1xx headers */
#define CURLH_PSEUDO (1<<4) /* pseudo headers */
typedef enum {
CURLHE_OK,
CURLHE_BADINDEX, /* header exists but not with this index */
CURLHE_MISSING, /* no such header exists */
CURLHE_NOHEADERS, /* no headers at all exist (yet) */
CURLHE_NOREQUEST, /* no request with this number was used */
CURLHE_OUT_OF_MEMORY, /* out of memory while processing */
CURLHE_BAD_ARGUMENT, /* a function argument was not okay */
CURLHE_NOT_BUILT_IN /* if API was disabled in the build */
} CURLHcode;
CURL_EXTERN CURLHcode curl_easy_header(CURL *easy,
const char *name,
size_t index,
unsigned int origin,
int request,
struct curl_header **hout);
CURL_EXTERN struct curl_header *curl_easy_nextheader(CURL *easy,
unsigned int origin,
int request,
struct curl_header *prev);
#ifdef __cplusplus
} /* end of extern "C" */
#endif
#endif /* CURLINC_HEADER_H */

View file

@ -1,5 +1,5 @@
#ifndef __CURL_MPRINTF_H #ifndef CURLINC_MPRINTF_H
#define __CURL_MPRINTF_H #define CURLINC_MPRINTF_H
/*************************************************************************** /***************************************************************************
* _ _ ____ _ * _ _ ____ _
* Project ___| | | | _ \| | * Project ___| | | | _ \| |
@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#include <stdarg.h> #include <stdarg.h>
@ -44,7 +46,7 @@ CURL_EXTERN char *curl_maprintf(const char *format, ...);
CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args); CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args);
#ifdef __cplusplus #ifdef __cplusplus
} } /* end of extern "C" */
#endif #endif
#endif /* __CURL_MPRINTF_H */ #endif /* CURLINC_MPRINTF_H */

View file

@ -1,5 +1,5 @@
#ifndef __CURL_MULTI_H #ifndef CURLINC_MULTI_H
#define __CURL_MULTI_H #define CURLINC_MULTI_H
/*************************************************************************** /***************************************************************************
* _ _ ____ _ * _ _ ____ _
* Project ___| | | | _ \| | * Project ___| | | | _ \| |
@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
/* /*
This is an "external" header file. Don't give away any internals here! This is an "external" header file. Don't give away any internals here!
@ -72,6 +74,10 @@ typedef enum {
attempted to get added - again */ attempted to get added - again */
CURLM_RECURSIVE_API_CALL, /* an api function was called from inside a CURLM_RECURSIVE_API_CALL, /* an api function was called from inside a
callback */ callback */
CURLM_WAKEUP_FAILURE, /* wakeup is unavailable or failed */
CURLM_BAD_FUNCTION_ARGUMENT, /* function called with a bad parameter */
CURLM_ABORTED_BY_CALLBACK,
CURLM_UNRECOVERABLE_POLL,
CURLM_LAST CURLM_LAST
} CURLMcode; } CURLMcode;
@ -118,7 +124,7 @@ struct curl_waitfd {
/* /*
* Name: curl_multi_init() * Name: curl_multi_init()
* *
* Desc: inititalize multi-style curl usage * Desc: initialize multi-style curl usage
* *
* Returns: a new CURLM handle to use in all 'curl_multi' functions. * Returns: a new CURLM handle to use in all 'curl_multi' functions.
*/ */
@ -173,6 +179,29 @@ CURL_EXTERN CURLMcode curl_multi_wait(CURLM *multi_handle,
int timeout_ms, int timeout_ms,
int *ret); 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() * Name: curl_multi_perform()
* *
@ -242,7 +271,7 @@ CURL_EXTERN CURLMsg *curl_multi_info_read(CURLM *multi_handle,
* value into the equivalent human readable error string. This is * value into the equivalent human readable error string. This is
* useful for printing meaningful error messages. * useful for printing meaningful error messages.
* *
* Returns: A pointer to a zero-terminated error message. * Returns: A pointer to a null-terminated error message.
*/ */
CURL_EXTERN const char *curl_multi_strerror(CURLMcode); CURL_EXTERN const char *curl_multi_strerror(CURLMcode);
@ -289,16 +318,16 @@ typedef int (*curl_multi_timer_callback)(CURLM *multi, /* multi handle */
void *userp); /* private callback void *userp); /* private callback
pointer */ pointer */
CURL_EXTERN CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s, CURL_EXTERN CURLMcode CURL_DEPRECATED(7.19.5, "Use curl_multi_socket_action()")
int *running_handles); curl_multi_socket(CURLM *multi_handle, curl_socket_t s, int *running_handles);
CURL_EXTERN CURLMcode curl_multi_socket_action(CURLM *multi_handle, CURL_EXTERN CURLMcode curl_multi_socket_action(CURLM *multi_handle,
curl_socket_t s, curl_socket_t s,
int ev_bitmask, int ev_bitmask,
int *running_handles); int *running_handles);
CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle, CURL_EXTERN CURLMcode CURL_DEPRECATED(7.19.5, "Use curl_multi_socket_action()")
int *running_handles); curl_multi_socket_all(CURLM *multi_handle, int *running_handles);
#ifndef CURL_ALLOW_OLD_MULTI_SOCKET #ifndef CURL_ALLOW_OLD_MULTI_SOCKET
/* This macro below was added in 7.16.3 to push users who recompile to use /* This macro below was added in 7.16.3 to push users who recompile to use
@ -319,68 +348,56 @@ CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle,
CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle, CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle,
long *milliseconds); 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 { typedef enum {
/* This is the socket callback function pointer */ /* 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 */ /* 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 */ /* 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 */ /* 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 */ /* 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 */ /* 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 */ /* 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 */ /* 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 /* a connection with a content-length longer than this
will not be considered for pipelining */ 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 /* a connection with a chunk length longer than this
will not be considered for pipelining */ 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 /* a list of site names(+port) that are blocked from pipelining */
pipelining */ CURLOPT(CURLMOPT_PIPELINING_SITE_BL, CURLOPTTYPE_OBJECTPOINT, 11),
CINIT(PIPELINING_SITE_BL, OBJECTPOINT, 11),
/* a list of server types that are blacklisted from /* a list of server types that are blocked from pipelining */
pipelining */ CURLOPT(CURLMOPT_PIPELINING_SERVER_BL, CURLOPTTYPE_OBJECTPOINT, 12),
CINIT(PIPELINING_SERVER_BL, OBJECTPOINT, 12),
/* maximum number of open connections in total */ /* 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 */ /* 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 */ /* 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 */ CURLMOPT_LASTENTRY /* the last unused */
} CURLMoption; } CURLMoption;
@ -414,12 +431,14 @@ CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle,
* Name: curl_push_callback * Name: curl_push_callback
* *
* Desc: This callback gets called when a new stream is being pushed by the * Desc: This callback gets called when a new stream is being pushed by the
* server. It approves or denies the new stream. * server. It approves or denies the new stream. It can also decide
* to completely fail the connection.
* *
* Returns: CURL_PUSH_OK or CURL_PUSH_DENY. * Returns: CURL_PUSH_OK, CURL_PUSH_DENY or CURL_PUSH_ERROROUT
*/ */
#define CURL_PUSH_OK 0 #define CURL_PUSH_OK 0
#define CURL_PUSH_DENY 1 #define CURL_PUSH_DENY 1
#define CURL_PUSH_ERROROUT 2 /* added in 7.72.0 */
struct curl_pushheaders; /* forward declaration only */ struct curl_pushheaders; /* forward declaration only */

View file

@ -0,0 +1,70 @@
#ifndef CURLINC_OPTIONS_H
#define CURLINC_OPTIONS_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
CURLOT_LONG, /* long (a range of values) */
CURLOT_VALUES, /* (a defined set or bitmask) */
CURLOT_OFF_T, /* curl_off_t (a range of values) */
CURLOT_OBJECT, /* pointer (void *) */
CURLOT_STRING, /* (char * to null-terminated buffer) */
CURLOT_SLIST, /* (struct curl_slist *) */
CURLOT_CBPTR, /* (void * passed as-is to a callback) */
CURLOT_BLOB, /* blob (struct curl_blob *) */
CURLOT_FUNCTION /* function pointer */
} curl_easytype;
/* Flag bits */
/* "alias" means it is provided for old programs to remain functional,
we prefer another name */
#define CURLOT_FLAG_ALIAS (1<<0)
/* The CURLOPTTYPE_* id ranges can still be used to figure out what type/size
to use for curl_easy_setopt() for the given id */
struct curl_easyoption {
const char *name;
CURLoption id;
curl_easytype type;
unsigned int flags;
};
CURL_EXTERN const struct curl_easyoption *
curl_easy_option_by_name(const char *name);
CURL_EXTERN const struct curl_easyoption *
curl_easy_option_by_id(CURLoption id);
CURL_EXTERN const struct curl_easyoption *
curl_easy_option_next(const struct curl_easyoption *prev);
#ifdef __cplusplus
} /* end of extern "C" */
#endif
#endif /* CURLINC_OPTIONS_H */

View file

@ -1,5 +1,5 @@
#ifndef __STDC_HEADERS_H #ifndef CURLINC_STDCHEADERS_H
#define __STDC_HEADERS_H #define CURLINC_STDCHEADERS_H
/*************************************************************************** /***************************************************************************
* _ _ ____ _ * _ _ ____ _
* Project ___| | | | _ \| | * Project ___| | | | _ \| |
@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#include <sys/types.h> #include <sys/types.h>
@ -30,4 +32,4 @@ size_t fwrite(const void *, size_t, size_t, FILE *);
int strcasecmp(const char *, const char *); int strcasecmp(const char *, const char *);
int strncasecmp(const char *, const char *, size_t); int strncasecmp(const char *, const char *, size_t);
#endif /* __STDC_HEADERS_H */ #endif /* CURLINC_STDCHEADERS_H */

View file

@ -1,5 +1,5 @@
#ifndef __CURL_SYSTEM_H #ifndef CURLINC_SYSTEM_H
#define __CURL_SYSTEM_H #define CURLINC_SYSTEM_H
/*************************************************************************** /***************************************************************************
* _ _ ____ _ * _ _ ____ _
* Project ___| | | | _ \| | * Project ___| | | | _ \| |
@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
/* /*
@ -98,22 +100,6 @@
# define CURL_SUFFIX_CURL_OFF_TU UL # define CURL_SUFFIX_CURL_OFF_TU UL
# define CURL_TYPEOF_CURL_SOCKLEN_T int # define CURL_TYPEOF_CURL_SOCKLEN_T int
#elif defined(__WATCOMC__)
# if defined(__386__)
# define CURL_TYPEOF_CURL_OFF_T __int64
# define CURL_FORMAT_CURL_OFF_T "I64d"
# define CURL_FORMAT_CURL_OFF_TU "I64u"
# define CURL_SUFFIX_CURL_OFF_T i64
# define CURL_SUFFIX_CURL_OFF_TU ui64
# else
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#elif defined(__POCC__) #elif defined(__POCC__)
# if (__POCC__ < 280) # if (__POCC__ < 280)
# define CURL_TYPEOF_CURL_OFF_T long # define CURL_TYPEOF_CURL_OFF_T long
@ -137,15 +123,26 @@
# define CURL_TYPEOF_CURL_SOCKLEN_T int # define CURL_TYPEOF_CURL_SOCKLEN_T int
#elif defined(__LCC__) #elif defined(__LCC__)
# define CURL_TYPEOF_CURL_OFF_T long # if defined(__MCST__) /* MCST eLbrus Compiler Collection */
# define CURL_FORMAT_CURL_OFF_T "ld" # define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_TU "lu" # define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_SUFFIX_CURL_OFF_T L # define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_TU UL # define CURL_SUFFIX_CURL_OFF_T L
# define CURL_TYPEOF_CURL_SOCKLEN_T int # 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__) #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_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld" # define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu" # define CURL_FORMAT_CURL_OFF_TU "llu"
@ -167,13 +164,33 @@
# endif # endif
# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int # define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
#elif defined(__MWERKS__) #elif defined(macintosh)
# include <ConditionalMacros.h>
# if TYPE_LONGLONG
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# else
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
#elif defined(__TANDEM)
# if ! defined(__LP64)
/* Required for 32-bit NonStop builds only. */
# define CURL_TYPEOF_CURL_OFF_T long long # define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld" # define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu" # define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL # define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL # define CURL_SUFFIX_CURL_OFF_TU ULL
# define CURL_TYPEOF_CURL_SOCKLEN_T int # define CURL_TYPEOF_CURL_SOCKLEN_T int
# endif
#elif defined(_WIN32_WCE) #elif defined(_WIN32_WCE)
# define CURL_TYPEOF_CURL_OFF_T __int64 # define CURL_TYPEOF_CURL_OFF_T __int64
@ -210,16 +227,14 @@
# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int # define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
#elif defined(__OS400__) #elif defined(__OS400__)
# if defined(__ILEC400__) # define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_TYPEOF_CURL_OFF_T long long # define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_T "lld" # define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_FORMAT_CURL_OFF_TU "llu" # define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_T LL # define CURL_SUFFIX_CURL_OFF_TU ULL
# define CURL_SUFFIX_CURL_OFF_TU ULL # define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t # define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_SYS_TYPES_H 1 # define CURL_PULL_SYS_SOCKET_H 1
# define CURL_PULL_SYS_SOCKET_H 1
# endif
#elif defined(__MVS__) #elif defined(__MVS__)
# if defined(__IBMC__) || defined(__IBMCPP__) # if defined(__IBMC__) || defined(__IBMCPP__)
@ -288,7 +303,6 @@
# define CURL_TYPEOF_CURL_SOCKLEN_T int # define CURL_TYPEOF_CURL_SOCKLEN_T int
#elif defined(__TINYC__) /* also known as tcc */ #elif defined(__TINYC__) /* also known as tcc */
# define CURL_TYPEOF_CURL_OFF_T long long # define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld" # define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu" # define CURL_FORMAT_CURL_OFF_TU "llu"
@ -377,6 +391,7 @@
# define CURL_SUFFIX_CURL_OFF_TU ULL # define CURL_SUFFIX_CURL_OFF_TU ULL
# elif defined(__LP64__) || \ # elif defined(__LP64__) || \
defined(__x86_64__) || defined(__ppc64__) || defined(__sparc64__) || \ defined(__x86_64__) || defined(__ppc64__) || defined(__sparc64__) || \
defined(__e2k__) || \
(defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 8) || \ (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 8) || \
(defined(__LONG_MAX__) && __LONG_MAX__ == 9223372036854775807L) (defined(__LONG_MAX__) && __LONG_MAX__ == 9223372036854775807L)
# define CURL_TYPEOF_CURL_OFF_T long # define CURL_TYPEOF_CURL_OFF_T long
@ -473,21 +488,21 @@
*/ */
#if defined(__BORLANDC__) && (__BORLANDC__ == 0x0551) #if defined(__BORLANDC__) && (__BORLANDC__ == 0x0551)
# define __CURL_OFF_T_C_HLPR2(x) x # define CURLINC_OFF_T_C_HLPR2(x) x
# define __CURL_OFF_T_C_HLPR1(x) __CURL_OFF_T_C_HLPR2(x) # define CURLINC_OFF_T_C_HLPR1(x) CURLINC_OFF_T_C_HLPR2(x)
# define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \ # define CURL_OFF_T_C(Val) CURLINC_OFF_T_C_HLPR1(Val) ## \
__CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_T) CURLINC_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_T)
# define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \ # define CURL_OFF_TU_C(Val) CURLINC_OFF_T_C_HLPR1(Val) ## \
__CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_TU) CURLINC_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_TU)
#else #else
# ifdef CURL_ISOCPP # ifdef CURL_ISOCPP
# define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val ## Suffix # define CURLINC_OFF_T_C_HLPR2(Val,Suffix) Val ## Suffix
# else # else
# define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val/**/Suffix # define CURLINC_OFF_T_C_HLPR2(Val,Suffix) Val/**/Suffix
# endif # endif
# define __CURL_OFF_T_C_HLPR1(Val,Suffix) __CURL_OFF_T_C_HLPR2(Val,Suffix) # define CURLINC_OFF_T_C_HLPR1(Val,Suffix) CURLINC_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_T_C(Val) CURLINC_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 CURL_OFF_TU_C(Val) CURLINC_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_TU)
#endif #endif
#endif /* __CURL_SYSTEM_H */ #endif /* CURLINC_SYSTEM_H */

View file

@ -1,5 +1,5 @@
#ifndef __CURL_TYPECHECK_GCC_H #ifndef CURLINC_TYPECHECK_GCC_H
#define __CURL_TYPECHECK_GCC_H #define CURLINC_TYPECHECK_GCC_H
/*************************************************************************** /***************************************************************************
* _ _ ____ _ * _ _ ____ _
* Project ___| | | | _ \| | * Project ___| | | | _ \| |
@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -20,15 +20,17 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
/* wraps curl_easy_setopt() with typechecking */ /* wraps curl_easy_setopt() with typechecking */
/* To add a new kind of warning, add an /* To add a new kind of warning, add an
* if(_curl_is_sometype_option(_curl_opt)) * if(curlcheck_sometype_option(_curl_opt))
* if(!_curl_is_sometype(value)) * if(!curlcheck_sometype(value))
* _curl_easy_setopt_err_sometype(); * _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 * _curl_easy_setopt_err_sometype below
* *
* NOTE: We use two nested 'if' statements here instead of the && operator, in * NOTE: We use two nested 'if' statements here instead of the && operator, in
@ -38,112 +40,116 @@
* To add an option that uses the same type as an existing option, you'll just * To add an option that uses the same type as an existing option, you'll just
* need to extend the appropriate _curl_*_option macro * need to extend the appropriate _curl_*_option macro
*/ */
#define curl_easy_setopt(handle, option, value) \ #define curl_easy_setopt(handle, option, value) \
__extension__ ({ \ __extension__({ \
__typeof__(option) _curl_opt = option; \ CURLoption _curl_opt = (option); \
if(__builtin_constant_p(_curl_opt)) { \ if(__builtin_constant_p(_curl_opt)) { \
if(_curl_is_long_option(_curl_opt)) \ CURL_IGNORE_DEPRECATION( \
if(!_curl_is_long(value)) \ if(curlcheck_long_option(_curl_opt)) \
_curl_easy_setopt_err_long(); \ if(!curlcheck_long(value)) \
if(_curl_is_off_t_option(_curl_opt)) \ _curl_easy_setopt_err_long(); \
if(!_curl_is_off_t(value)) \ if(curlcheck_off_t_option(_curl_opt)) \
_curl_easy_setopt_err_curl_off_t(); \ if(!curlcheck_off_t(value)) \
if(_curl_is_string_option(_curl_opt)) \ _curl_easy_setopt_err_curl_off_t(); \
if(!_curl_is_string(value)) \ if(curlcheck_string_option(_curl_opt)) \
_curl_easy_setopt_err_string(); \ if(!curlcheck_string(value)) \
if(_curl_is_write_cb_option(_curl_opt)) \ _curl_easy_setopt_err_string(); \
if(!_curl_is_write_cb(value)) \ if(curlcheck_write_cb_option(_curl_opt)) \
_curl_easy_setopt_err_write_callback(); \ if(!curlcheck_write_cb(value)) \
if((_curl_opt) == CURLOPT_RESOLVER_START_FUNCTION) \ _curl_easy_setopt_err_write_callback(); \
if(!_curl_is_resolver_start_callback(value)) \ if((_curl_opt) == CURLOPT_RESOLVER_START_FUNCTION) \
_curl_easy_setopt_err_resolver_start_callback(); \ if(!curlcheck_resolver_start_callback(value)) \
if((_curl_opt) == CURLOPT_READFUNCTION) \ _curl_easy_setopt_err_resolver_start_callback(); \
if(!_curl_is_read_cb(value)) \ if((_curl_opt) == CURLOPT_READFUNCTION) \
_curl_easy_setopt_err_read_cb(); \ if(!curlcheck_read_cb(value)) \
if((_curl_opt) == CURLOPT_IOCTLFUNCTION) \ _curl_easy_setopt_err_read_cb(); \
if(!_curl_is_ioctl_cb(value)) \ if((_curl_opt) == CURLOPT_IOCTLFUNCTION) \
_curl_easy_setopt_err_ioctl_cb(); \ if(!curlcheck_ioctl_cb(value)) \
if((_curl_opt) == CURLOPT_SOCKOPTFUNCTION) \ _curl_easy_setopt_err_ioctl_cb(); \
if(!_curl_is_sockopt_cb(value)) \ if((_curl_opt) == CURLOPT_SOCKOPTFUNCTION) \
_curl_easy_setopt_err_sockopt_cb(); \ if(!curlcheck_sockopt_cb(value)) \
if((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION) \ _curl_easy_setopt_err_sockopt_cb(); \
if(!_curl_is_opensocket_cb(value)) \ if((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION) \
_curl_easy_setopt_err_opensocket_cb(); \ if(!curlcheck_opensocket_cb(value)) \
if((_curl_opt) == CURLOPT_PROGRESSFUNCTION) \ _curl_easy_setopt_err_opensocket_cb(); \
if(!_curl_is_progress_cb(value)) \ if((_curl_opt) == CURLOPT_PROGRESSFUNCTION) \
_curl_easy_setopt_err_progress_cb(); \ if(!curlcheck_progress_cb(value)) \
if((_curl_opt) == CURLOPT_DEBUGFUNCTION) \ _curl_easy_setopt_err_progress_cb(); \
if(!_curl_is_debug_cb(value)) \ if((_curl_opt) == CURLOPT_DEBUGFUNCTION) \
_curl_easy_setopt_err_debug_cb(); \ if(!curlcheck_debug_cb(value)) \
if((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION) \ _curl_easy_setopt_err_debug_cb(); \
if(!_curl_is_ssl_ctx_cb(value)) \ if((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION) \
_curl_easy_setopt_err_ssl_ctx_cb(); \ if(!curlcheck_ssl_ctx_cb(value)) \
if(_curl_is_conv_cb_option(_curl_opt)) \ _curl_easy_setopt_err_ssl_ctx_cb(); \
if(!_curl_is_conv_cb(value)) \ if(curlcheck_conv_cb_option(_curl_opt)) \
_curl_easy_setopt_err_conv_cb(); \ if(!curlcheck_conv_cb(value)) \
if((_curl_opt) == CURLOPT_SEEKFUNCTION) \ _curl_easy_setopt_err_conv_cb(); \
if(!_curl_is_seek_cb(value)) \ if((_curl_opt) == CURLOPT_SEEKFUNCTION) \
_curl_easy_setopt_err_seek_cb(); \ if(!curlcheck_seek_cb(value)) \
if(_curl_is_cb_data_option(_curl_opt)) \ _curl_easy_setopt_err_seek_cb(); \
if(!_curl_is_cb_data(value)) \ if(curlcheck_cb_data_option(_curl_opt)) \
_curl_easy_setopt_err_cb_data(); \ if(!curlcheck_cb_data(value)) \
if((_curl_opt) == CURLOPT_ERRORBUFFER) \ _curl_easy_setopt_err_cb_data(); \
if(!_curl_is_error_buffer(value)) \ if((_curl_opt) == CURLOPT_ERRORBUFFER) \
_curl_easy_setopt_err_error_buffer(); \ if(!curlcheck_error_buffer(value)) \
if((_curl_opt) == CURLOPT_STDERR) \ _curl_easy_setopt_err_error_buffer(); \
if(!_curl_is_FILE(value)) \ if((_curl_opt) == CURLOPT_STDERR) \
_curl_easy_setopt_err_FILE(); \ if(!curlcheck_FILE(value)) \
if(_curl_is_postfields_option(_curl_opt)) \ _curl_easy_setopt_err_FILE(); \
if(!_curl_is_postfields(value)) \ if(curlcheck_postfields_option(_curl_opt)) \
_curl_easy_setopt_err_postfields(); \ if(!curlcheck_postfields(value)) \
if((_curl_opt) == CURLOPT_HTTPPOST) \ _curl_easy_setopt_err_postfields(); \
if(!_curl_is_arr((value), struct curl_httppost)) \ if((_curl_opt) == CURLOPT_HTTPPOST) \
_curl_easy_setopt_err_curl_httpost(); \ if(!curlcheck_arr((value), struct curl_httppost)) \
if((_curl_opt) == CURLOPT_MIMEPOST) \ _curl_easy_setopt_err_curl_httpost(); \
if(!_curl_is_ptr((value), curl_mime)) \ if((_curl_opt) == CURLOPT_MIMEPOST) \
_curl_easy_setopt_err_curl_mimepost(); \ if(!curlcheck_ptr((value), curl_mime)) \
if(_curl_is_slist_option(_curl_opt)) \ _curl_easy_setopt_err_curl_mimepost(); \
if(!_curl_is_arr((value), struct curl_slist)) \ if(curlcheck_slist_option(_curl_opt)) \
_curl_easy_setopt_err_curl_slist(); \ if(!curlcheck_arr((value), struct curl_slist)) \
if((_curl_opt) == CURLOPT_SHARE) \ _curl_easy_setopt_err_curl_slist(); \
if(!_curl_is_ptr((value), CURLSH)) \ if((_curl_opt) == CURLOPT_SHARE) \
_curl_easy_setopt_err_CURLSH(); \ if(!curlcheck_ptr((value), CURLSH)) \
} \ _curl_easy_setopt_err_CURLSH(); \
curl_easy_setopt(handle, _curl_opt, value); \ ) \
}) } \
curl_easy_setopt(handle, _curl_opt, value); \
})
/* wraps curl_easy_getinfo() with typechecking */ /* wraps curl_easy_getinfo() with typechecking */
#define curl_easy_getinfo(handle, info, arg) \ #define curl_easy_getinfo(handle, info, arg) \
__extension__ ({ \ __extension__({ \
__typeof__(info) _curl_info = info; \ CURLINFO _curl_info = (info); \
if(__builtin_constant_p(_curl_info)) { \ if(__builtin_constant_p(_curl_info)) { \
if(_curl_is_string_info(_curl_info)) \ CURL_IGNORE_DEPRECATION( \
if(!_curl_is_arr((arg), char *)) \ if(curlcheck_string_info(_curl_info)) \
_curl_easy_getinfo_err_string(); \ if(!curlcheck_arr((arg), char *)) \
if(_curl_is_long_info(_curl_info)) \ _curl_easy_getinfo_err_string(); \
if(!_curl_is_arr((arg), long)) \ if(curlcheck_long_info(_curl_info)) \
_curl_easy_getinfo_err_long(); \ if(!curlcheck_arr((arg), long)) \
if(_curl_is_double_info(_curl_info)) \ _curl_easy_getinfo_err_long(); \
if(!_curl_is_arr((arg), double)) \ if(curlcheck_double_info(_curl_info)) \
_curl_easy_getinfo_err_double(); \ if(!curlcheck_arr((arg), double)) \
if(_curl_is_slist_info(_curl_info)) \ _curl_easy_getinfo_err_double(); \
if(!_curl_is_arr((arg), struct curl_slist *)) \ if(curlcheck_slist_info(_curl_info)) \
_curl_easy_getinfo_err_curl_slist(); \ if(!curlcheck_arr((arg), struct curl_slist *)) \
if(_curl_is_tlssessioninfo_info(_curl_info)) \ _curl_easy_getinfo_err_curl_slist(); \
if(!_curl_is_arr((arg), struct curl_tlssessioninfo *)) \ if(curlcheck_tlssessioninfo_info(_curl_info)) \
_curl_easy_getinfo_err_curl_tlssesssioninfo(); \ if(!curlcheck_arr((arg), struct curl_tlssessioninfo *)) \
if(_curl_is_certinfo_info(_curl_info)) \ _curl_easy_getinfo_err_curl_tlssesssioninfo(); \
if(!_curl_is_arr((arg), struct curl_certinfo *)) \ if(curlcheck_certinfo_info(_curl_info)) \
_curl_easy_getinfo_err_curl_certinfo(); \ if(!curlcheck_arr((arg), struct curl_certinfo *)) \
if(_curl_is_socket_info(_curl_info)) \ _curl_easy_getinfo_err_curl_certinfo(); \
if(!_curl_is_arr((arg), curl_socket_t)) \ if(curlcheck_socket_info(_curl_info)) \
_curl_easy_getinfo_err_curl_socket(); \ if(!curlcheck_arr((arg), curl_socket_t)) \
if(_curl_is_off_t_info(_curl_info)) \ _curl_easy_getinfo_err_curl_socket(); \
if(!_curl_is_arr((arg), curl_off_t)) \ if(curlcheck_off_t_info(_curl_info)) \
_curl_easy_getinfo_err_curl_off_t(); \ if(!curlcheck_arr((arg), curl_off_t)) \
} \ _curl_easy_getinfo_err_curl_off_t(); \
curl_easy_getinfo(handle, _curl_info, arg); \ ) \
}) } \
curl_easy_getinfo(handle, _curl_info, arg); \
})
/* /*
* For now, just make sure that the functions are called with three arguments * For now, just make sure that the functions are called with three arguments
@ -156,83 +162,83 @@ __extension__ ({ \
* functions */ * functions */
/* To define a new warning, use _CURL_WARNING(identifier, "message") */ /* To define a new warning, use _CURL_WARNING(identifier, "message") */
#define _CURL_WARNING(id, message) \ #define CURLWARNING(id, message) \
static void __attribute__((__warning__(message))) \ static void __attribute__((__warning__(message))) \
__attribute__((__unused__)) __attribute__((__noinline__)) \ __attribute__((__unused__)) __attribute__((__noinline__)) \
id(void) { __asm__(""); } 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_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_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 " "curl_easy_setopt expects a "
"string ('char *' or char[]) argument for this option" "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_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_easy_setopt expects a "
"curl_resolver_start_callback argument for this option" "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_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_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_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_easy_setopt expects a "
"curl_opensocket_callback argument for this option" "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_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_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_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_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_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 " "curl_easy_setopt expects a "
"private data pointer as argument for this option") "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 " "curl_easy_setopt expects a "
"char buffer of CURL_ERROR_SIZE as argument for this option") "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_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_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 *' " "curl_easy_setopt expects a 'struct curl_httppost *' "
"argument for this option") "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 *' " "curl_easy_setopt expects a 'curl_mime *' "
"argument for this option") "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_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_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_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_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_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_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 " "curl_easy_getinfo expects a pointer to "
"'struct curl_tlssessioninfo *' for this info") "'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 " "curl_easy_getinfo expects a pointer to "
"'struct curl_certinfo *' for this info") "'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_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") "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 */ /* groups of curl_easy_setops options that take the same type of argument */
@ -244,14 +250,14 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
*/ */
/* evaluates to true if option takes a long argument */ /* 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) (0 < (option) && (option) < CURLOPTTYPE_OBJECTPOINT)
#define _curl_is_off_t_option(option) \ #define curlcheck_off_t_option(option) \
((option) > CURLOPTTYPE_OFF_T) (((option) > CURLOPTTYPE_OFF_T) && ((option) < CURLOPTTYPE_BLOB))
/* evaluates to true if option takes a char* argument */ /* 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_ABSTRACT_UNIX_SOCKET || \
(option) == CURLOPT_ACCEPT_ENCODING || \ (option) == CURLOPT_ACCEPT_ENCODING || \
(option) == CURLOPT_ALTSVC || \ (option) == CURLOPT_ALTSVC || \
@ -270,9 +276,10 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
(option) == CURLOPT_DNS_SERVERS || \ (option) == CURLOPT_DNS_SERVERS || \
(option) == CURLOPT_DOH_URL || \ (option) == CURLOPT_DOH_URL || \
(option) == CURLOPT_EGDSOCKET || \ (option) == CURLOPT_EGDSOCKET || \
(option) == CURLOPT_FTPPORT || \
(option) == CURLOPT_FTP_ACCOUNT || \ (option) == CURLOPT_FTP_ACCOUNT || \
(option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \ (option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \
(option) == CURLOPT_FTPPORT || \
(option) == CURLOPT_HSTS || \
(option) == CURLOPT_INTERFACE || \ (option) == CURLOPT_INTERFACE || \
(option) == CURLOPT_ISSUERCERT || \ (option) == CURLOPT_ISSUERCERT || \
(option) == CURLOPT_KEYPASSWD || \ (option) == CURLOPT_KEYPASSWD || \
@ -285,33 +292,40 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
(option) == CURLOPT_PASSWORD || \ (option) == CURLOPT_PASSWORD || \
(option) == CURLOPT_PINNEDPUBLICKEY || \ (option) == CURLOPT_PINNEDPUBLICKEY || \
(option) == CURLOPT_PRE_PROXY || \ (option) == CURLOPT_PRE_PROXY || \
(option) == CURLOPT_PROTOCOLS_STR || \
(option) == CURLOPT_PROXY || \ (option) == CURLOPT_PROXY || \
(option) == CURLOPT_PROXYPASSWORD || \
(option) == CURLOPT_PROXYUSERNAME || \
(option) == CURLOPT_PROXYUSERPWD || \
(option) == CURLOPT_PROXY_CAINFO || \ (option) == CURLOPT_PROXY_CAINFO || \
(option) == CURLOPT_PROXY_CAPATH || \ (option) == CURLOPT_PROXY_CAPATH || \
(option) == CURLOPT_PROXY_CRLFILE || \ (option) == CURLOPT_PROXY_CRLFILE || \
(option) == CURLOPT_PROXY_ISSUERCERT || \
(option) == CURLOPT_PROXY_KEYPASSWD || \ (option) == CURLOPT_PROXY_KEYPASSWD || \
(option) == CURLOPT_PROXY_PINNEDPUBLICKEY || \ (option) == CURLOPT_PROXY_PINNEDPUBLICKEY || \
(option) == CURLOPT_PROXY_SERVICE_NAME || \ (option) == CURLOPT_PROXY_SERVICE_NAME || \
(option) == CURLOPT_PROXY_SSL_CIPHER_LIST || \
(option) == CURLOPT_PROXY_SSLCERT || \ (option) == CURLOPT_PROXY_SSLCERT || \
(option) == CURLOPT_PROXY_SSLCERTTYPE || \ (option) == CURLOPT_PROXY_SSLCERTTYPE || \
(option) == CURLOPT_PROXY_SSLKEY || \ (option) == CURLOPT_PROXY_SSLKEY || \
(option) == CURLOPT_PROXY_SSLKEYTYPE || \ (option) == CURLOPT_PROXY_SSLKEYTYPE || \
(option) == CURLOPT_PROXY_SSL_CIPHER_LIST || \ (option) == CURLOPT_PROXY_TLS13_CIPHERS || \
(option) == CURLOPT_PROXY_TLSAUTH_PASSWORD || \ (option) == CURLOPT_PROXY_TLSAUTH_PASSWORD || \
(option) == CURLOPT_PROXY_TLSAUTH_USERNAME || \
(option) == CURLOPT_PROXY_TLSAUTH_TYPE || \ (option) == CURLOPT_PROXY_TLSAUTH_TYPE || \
(option) == CURLOPT_PROXY_TLSAUTH_USERNAME || \
(option) == CURLOPT_PROXYPASSWORD || \
(option) == CURLOPT_PROXYUSERNAME || \
(option) == CURLOPT_PROXYUSERPWD || \
(option) == CURLOPT_RANDOM_FILE || \ (option) == CURLOPT_RANDOM_FILE || \
(option) == CURLOPT_RANGE || \ (option) == CURLOPT_RANGE || \
(option) == CURLOPT_REDIR_PROTOCOLS_STR || \
(option) == CURLOPT_REFERER || \ (option) == CURLOPT_REFERER || \
(option) == CURLOPT_REQUEST_TARGET || \
(option) == CURLOPT_RTSP_SESSION_ID || \ (option) == CURLOPT_RTSP_SESSION_ID || \
(option) == CURLOPT_RTSP_STREAM_URI || \ (option) == CURLOPT_RTSP_STREAM_URI || \
(option) == CURLOPT_RTSP_TRANSPORT || \ (option) == CURLOPT_RTSP_TRANSPORT || \
(option) == CURLOPT_SASL_AUTHZID || \
(option) == CURLOPT_SERVICE_NAME || \ (option) == CURLOPT_SERVICE_NAME || \
(option) == CURLOPT_SOCKS5_GSSAPI_SERVICE || \ (option) == CURLOPT_SOCKS5_GSSAPI_SERVICE || \
(option) == CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 || \ (option) == CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 || \
(option) == CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256 || \
(option) == CURLOPT_SSH_KNOWNHOSTS || \ (option) == CURLOPT_SSH_KNOWNHOSTS || \
(option) == CURLOPT_SSH_PRIVATE_KEYFILE || \ (option) == CURLOPT_SSH_PRIVATE_KEYFILE || \
(option) == CURLOPT_SSH_PUBLIC_KEYFILE || \ (option) == CURLOPT_SSH_PUBLIC_KEYFILE || \
@ -321,6 +335,7 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
(option) == CURLOPT_SSLKEY || \ (option) == CURLOPT_SSLKEY || \
(option) == CURLOPT_SSLKEYTYPE || \ (option) == CURLOPT_SSLKEYTYPE || \
(option) == CURLOPT_SSL_CIPHER_LIST || \ (option) == CURLOPT_SSL_CIPHER_LIST || \
(option) == CURLOPT_TLS13_CIPHERS || \
(option) == CURLOPT_TLSAUTH_PASSWORD || \ (option) == CURLOPT_TLSAUTH_PASSWORD || \
(option) == CURLOPT_TLSAUTH_TYPE || \ (option) == CURLOPT_TLSAUTH_TYPE || \
(option) == CURLOPT_TLSAUTH_USERNAME || \ (option) == CURLOPT_TLSAUTH_USERNAME || \
@ -328,32 +343,36 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
(option) == CURLOPT_URL || \ (option) == CURLOPT_URL || \
(option) == CURLOPT_USERAGENT || \ (option) == CURLOPT_USERAGENT || \
(option) == CURLOPT_USERNAME || \ (option) == CURLOPT_USERNAME || \
(option) == CURLOPT_AWS_SIGV4 || \
(option) == CURLOPT_USERPWD || \ (option) == CURLOPT_USERPWD || \
(option) == CURLOPT_XOAUTH2_BEARER || \ (option) == CURLOPT_XOAUTH2_BEARER || \
(option) == CURLOPT_SSL_EC_CURVES || \
0) 0)
/* evaluates to true if option takes a curl_write_callback argument */ /* evaluates to true if option takes a curl_write_callback argument */
#define _curl_is_write_cb_option(option) \ #define curlcheck_write_cb_option(option) \
((option) == CURLOPT_HEADERFUNCTION || \ ((option) == CURLOPT_HEADERFUNCTION || \
(option) == CURLOPT_WRITEFUNCTION) (option) == CURLOPT_WRITEFUNCTION)
/* evaluates to true if option takes a curl_conv_callback argument */ /* evaluates to true if option takes a curl_conv_callback argument */
#define _curl_is_conv_cb_option(option) \ #define curlcheck_conv_cb_option(option) \
((option) == CURLOPT_CONV_TO_NETWORK_FUNCTION || \ ((option) == CURLOPT_CONV_TO_NETWORK_FUNCTION || \
(option) == CURLOPT_CONV_FROM_NETWORK_FUNCTION || \ (option) == CURLOPT_CONV_FROM_NETWORK_FUNCTION || \
(option) == CURLOPT_CONV_FROM_UTF8_FUNCTION) (option) == CURLOPT_CONV_FROM_UTF8_FUNCTION)
/* evaluates to true if option takes a data argument to pass to a callback */ /* 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_CHUNK_DATA || \
(option) == CURLOPT_CLOSESOCKETDATA || \ (option) == CURLOPT_CLOSESOCKETDATA || \
(option) == CURLOPT_DEBUGDATA || \ (option) == CURLOPT_DEBUGDATA || \
(option) == CURLOPT_FNMATCH_DATA || \ (option) == CURLOPT_FNMATCH_DATA || \
(option) == CURLOPT_HEADERDATA || \ (option) == CURLOPT_HEADERDATA || \
(option) == CURLOPT_HSTSREADDATA || \
(option) == CURLOPT_HSTSWRITEDATA || \
(option) == CURLOPT_INTERLEAVEDATA || \ (option) == CURLOPT_INTERLEAVEDATA || \
(option) == CURLOPT_IOCTLDATA || \ (option) == CURLOPT_IOCTLDATA || \
(option) == CURLOPT_OPENSOCKETDATA || \ (option) == CURLOPT_OPENSOCKETDATA || \
(option) == CURLOPT_PRIVATE || \ (option) == CURLOPT_PREREQDATA || \
(option) == CURLOPT_PROGRESSDATA || \ (option) == CURLOPT_PROGRESSDATA || \
(option) == CURLOPT_READDATA || \ (option) == CURLOPT_READDATA || \
(option) == CURLOPT_SEEKDATA || \ (option) == CURLOPT_SEEKDATA || \
@ -362,17 +381,18 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
(option) == CURLOPT_SSL_CTX_DATA || \ (option) == CURLOPT_SSL_CTX_DATA || \
(option) == CURLOPT_WRITEDATA || \ (option) == CURLOPT_WRITEDATA || \
(option) == CURLOPT_RESOLVER_START_DATA || \ (option) == CURLOPT_RESOLVER_START_DATA || \
(option) == CURLOPT_CURLU || \ (option) == CURLOPT_TRAILERDATA || \
(option) == CURLOPT_SSH_HOSTKEYDATA || \
0) 0)
/* evaluates to true if option takes a POST data argument (void* or char*) */ /* 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_POSTFIELDS || \
(option) == CURLOPT_COPYPOSTFIELDS || \ (option) == CURLOPT_COPYPOSTFIELDS || \
0) 0)
/* evaluates to true if option takes a struct curl_slist * argument */ /* 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_HTTP200ALIASES || \
(option) == CURLOPT_HTTPHEADER || \ (option) == CURLOPT_HTTPHEADER || \
(option) == CURLOPT_MAIL_RCPT || \ (option) == CURLOPT_MAIL_RCPT || \
@ -382,45 +402,47 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
(option) == CURLOPT_QUOTE || \ (option) == CURLOPT_QUOTE || \
(option) == CURLOPT_RESOLVE || \ (option) == CURLOPT_RESOLVE || \
(option) == CURLOPT_TELNETOPTIONS || \ (option) == CURLOPT_TELNETOPTIONS || \
(option) == CURLOPT_CONNECT_TO || \
0) 0)
/* groups of curl_easy_getinfo infos that take the same type of argument */ /* groups of curl_easy_getinfo infos that take the same type of argument */
/* evaluates to true if info expects a pointer to char * 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) (CURLINFO_STRING < (info) && (info) < CURLINFO_LONG && \
(info) != CURLINFO_PRIVATE)
/* evaluates to true if info expects a pointer to long argument */ /* 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) (CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE)
/* evaluates to true if info expects a pointer to double argument */ /* 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) (CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST)
/* true if info expects a pointer to struct curl_slist * argument */ /* 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)) (((info) == CURLINFO_SSL_ENGINES) || ((info) == CURLINFO_COOKIELIST))
/* true if info expects a pointer to struct curl_tlssessioninfo * argument */ /* 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)) (((info) == CURLINFO_TLS_SSL_PTR) || ((info) == CURLINFO_TLS_SESSION))
/* true if info expects a pointer to struct curl_certinfo * argument */ /* 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 */ /* 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) (CURLINFO_SOCKET < (info) && (info) < CURLINFO_OFF_T)
/* true if info expects a pointer to curl_off_t argument */ /* 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)) (CURLINFO_OFF_T < (info))
/* typecheck helpers -- check whether given expression has requested type*/ /* 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 * otherwise define a new macro. Search for __builtin_types_compatible_p
* in the GCC manual. * in the GCC manual.
* NOTE: these macros MUST NOT EVALUATE their arguments! The argument is * NOTE: these macros MUST NOT EVALUATE their arguments! The argument is
@ -430,35 +452,35 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
*/ */
/* XXX: should evaluate to true if expr is a pointer */ /* 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 *)) (sizeof(expr) == sizeof(void *))
/* evaluates to true if expr is NULL */ /* evaluates to true if expr is NULL */
/* XXX: must not evaluate expr, so this check is not accurate */ /* 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))) (__builtin_types_compatible_p(__typeof__(expr), __typeof__(NULL)))
/* evaluates to true if expr is type*, const type* or NULL */ /* evaluates to true if expr is type*, const type* or NULL */
#define _curl_is_ptr(expr, type) \ #define curlcheck_ptr(expr, type) \
(_curl_is_NULL(expr) || \ (curlcheck_NULL(expr) || \
__builtin_types_compatible_p(__typeof__(expr), type *) || \ __builtin_types_compatible_p(__typeof__(expr), type *) || \
__builtin_types_compatible_p(__typeof__(expr), const type *)) __builtin_types_compatible_p(__typeof__(expr), const type *))
/* evaluates to true if expr is one of type[], type*, NULL or const type* */ /* evaluates to true if expr is one of type[], type*, NULL or const type* */
#define _curl_is_arr(expr, type) \ #define curlcheck_arr(expr, type) \
(_curl_is_ptr((expr), type) || \ (curlcheck_ptr((expr), type) || \
__builtin_types_compatible_p(__typeof__(expr), type [])) __builtin_types_compatible_p(__typeof__(expr), type []))
/* evaluates to true if expr is a string */ /* evaluates to true if expr is a string */
#define _curl_is_string(expr) \ #define curlcheck_string(expr) \
(_curl_is_arr((expr), char) || \ (curlcheck_arr((expr), char) || \
_curl_is_arr((expr), signed char) || \ curlcheck_arr((expr), signed char) || \
_curl_is_arr((expr), unsigned char)) curlcheck_arr((expr), unsigned char))
/* evaluates to true if expr is a long (no matter the signedness) /* 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 * XXX: for now, int is also accepted (and therefore short and char, which
* are promoted to int when passed to a variadic function) */ * 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), long) || \
__builtin_types_compatible_p(__typeof__(expr), signed long) || \ __builtin_types_compatible_p(__typeof__(expr), signed long) || \
__builtin_types_compatible_p(__typeof__(expr), unsigned long) || \ __builtin_types_compatible_p(__typeof__(expr), unsigned long) || \
@ -473,59 +495,59 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
__builtin_types_compatible_p(__typeof__(expr), unsigned char)) __builtin_types_compatible_p(__typeof__(expr), unsigned char))
/* evaluates to true if expr is of type curl_off_t */ /* 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)) (__builtin_types_compatible_p(__typeof__(expr), curl_off_t))
/* evaluates to true if expr is abuffer suitable for CURLOPT_ERRORBUFFER */ /* evaluates to true if expr is abuffer suitable for CURLOPT_ERRORBUFFER */
/* XXX: also check size of an char[] array? */ /* XXX: also check size of an char[] array? */
#define _curl_is_error_buffer(expr) \ #define curlcheck_error_buffer(expr) \
(_curl_is_NULL(expr) || \ (curlcheck_NULL(expr) || \
__builtin_types_compatible_p(__typeof__(expr), char *) || \ __builtin_types_compatible_p(__typeof__(expr), char *) || \
__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* */ /* evaluates to true if expr is of type (const) void* or (const) FILE* */
#if 0 #if 0
#define _curl_is_cb_data(expr) \ #define curlcheck_cb_data(expr) \
(_curl_is_ptr((expr), void) || \ (curlcheck_ptr((expr), void) || \
_curl_is_ptr((expr), FILE)) curlcheck_ptr((expr), FILE))
#else /* be less strict */ #else /* be less strict */
#define _curl_is_cb_data(expr) \ #define curlcheck_cb_data(expr) \
_curl_is_any_ptr(expr) curlcheck_any_ptr(expr)
#endif #endif
/* evaluates to true if expr is of type FILE* */ /* evaluates to true if expr is of type FILE* */
#define _curl_is_FILE(expr) \ #define curlcheck_FILE(expr) \
(_curl_is_NULL(expr) || \ (curlcheck_NULL(expr) || \
(__builtin_types_compatible_p(__typeof__(expr), FILE *))) (__builtin_types_compatible_p(__typeof__(expr), FILE *)))
/* evaluates to true if expr can be passed as POST data (void* or char*) */ /* evaluates to true if expr can be passed as POST data (void* or char*) */
#define _curl_is_postfields(expr) \ #define curlcheck_postfields(expr) \
(_curl_is_ptr((expr), void) || \ (curlcheck_ptr((expr), void) || \
_curl_is_arr((expr), char) || \ curlcheck_arr((expr), char) || \
_curl_is_arr((expr), unsigned char)) curlcheck_arr((expr), unsigned char))
/* helper: __builtin_types_compatible_p distinguishes between functions and /* helper: __builtin_types_compatible_p distinguishes between functions and
* function pointers, hide it */ * function pointers, hide it */
#define _curl_callback_compatible(func, type) \ #define curlcheck_cb_compatible(func, type) \
(__builtin_types_compatible_p(__typeof__(func), type) || \ (__builtin_types_compatible_p(__typeof__(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 */ /* evaluates to true if expr is of type curl_resolver_start_callback */
#define _curl_is_resolver_start_callback(expr) \ #define curlcheck_resolver_start_callback(expr) \
(_curl_is_NULL(expr) || \ (curlcheck_NULL(expr) || \
_curl_callback_compatible((expr), curl_resolver_start_callback)) curlcheck_cb_compatible((expr), curl_resolver_start_callback))
/* evaluates to true if expr is of type curl_read_callback or "similar" */ /* evaluates to true if expr is of type curl_read_callback or "similar" */
#define _curl_is_read_cb(expr) \ #define curlcheck_read_cb(expr) \
(_curl_is_NULL(expr) || \ (curlcheck_NULL(expr) || \
_curl_callback_compatible((expr), __typeof__(fread) *) || \ curlcheck_cb_compatible((expr), __typeof__(fread) *) || \
_curl_callback_compatible((expr), curl_read_callback) || \ curlcheck_cb_compatible((expr), curl_read_callback) || \
_curl_callback_compatible((expr), _curl_read_callback1) || \ curlcheck_cb_compatible((expr), _curl_read_callback1) || \
_curl_callback_compatible((expr), _curl_read_callback2) || \ curlcheck_cb_compatible((expr), _curl_read_callback2) || \
_curl_callback_compatible((expr), _curl_read_callback3) || \ curlcheck_cb_compatible((expr), _curl_read_callback3) || \
_curl_callback_compatible((expr), _curl_read_callback4) || \ curlcheck_cb_compatible((expr), _curl_read_callback4) || \
_curl_callback_compatible((expr), _curl_read_callback5) || \ curlcheck_cb_compatible((expr), _curl_read_callback5) || \
_curl_callback_compatible((expr), _curl_read_callback6)) curlcheck_cb_compatible((expr), _curl_read_callback6))
typedef size_t (*_curl_read_callback1)(char *, size_t, size_t, void *); 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_callback2)(char *, size_t, size_t, const void *);
typedef size_t (*_curl_read_callback3)(char *, size_t, size_t, FILE *); typedef size_t (*_curl_read_callback3)(char *, size_t, size_t, FILE *);
@ -534,16 +556,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 *); 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" */ /* evaluates to true if expr is of type curl_write_callback or "similar" */
#define _curl_is_write_cb(expr) \ #define curlcheck_write_cb(expr) \
(_curl_is_read_cb(expr) || \ (curlcheck_read_cb(expr) || \
_curl_callback_compatible((expr), __typeof__(fwrite) *) || \ curlcheck_cb_compatible((expr), __typeof__(fwrite) *) || \
_curl_callback_compatible((expr), curl_write_callback) || \ curlcheck_cb_compatible((expr), curl_write_callback) || \
_curl_callback_compatible((expr), _curl_write_callback1) || \ curlcheck_cb_compatible((expr), _curl_write_callback1) || \
_curl_callback_compatible((expr), _curl_write_callback2) || \ curlcheck_cb_compatible((expr), _curl_write_callback2) || \
_curl_callback_compatible((expr), _curl_write_callback3) || \ curlcheck_cb_compatible((expr), _curl_write_callback3) || \
_curl_callback_compatible((expr), _curl_write_callback4) || \ curlcheck_cb_compatible((expr), _curl_write_callback4) || \
_curl_callback_compatible((expr), _curl_write_callback5) || \ curlcheck_cb_compatible((expr), _curl_write_callback5) || \
_curl_callback_compatible((expr), _curl_write_callback6)) 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_callback1)(const char *, size_t, size_t, void *);
typedef size_t (*_curl_write_callback2)(const char *, size_t, size_t, typedef size_t (*_curl_write_callback2)(const char *, size_t, size_t,
const void *); const void *);
@ -554,37 +576,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 *); 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" */ /* evaluates to true if expr is of type curl_ioctl_callback or "similar" */
#define _curl_is_ioctl_cb(expr) \ #define curlcheck_ioctl_cb(expr) \
(_curl_is_NULL(expr) || \ (curlcheck_NULL(expr) || \
_curl_callback_compatible((expr), curl_ioctl_callback) || \ curlcheck_cb_compatible((expr), curl_ioctl_callback) || \
_curl_callback_compatible((expr), _curl_ioctl_callback1) || \ curlcheck_cb_compatible((expr), _curl_ioctl_callback1) || \
_curl_callback_compatible((expr), _curl_ioctl_callback2) || \ curlcheck_cb_compatible((expr), _curl_ioctl_callback2) || \
_curl_callback_compatible((expr), _curl_ioctl_callback3) || \ curlcheck_cb_compatible((expr), _curl_ioctl_callback3) || \
_curl_callback_compatible((expr), _curl_ioctl_callback4)) curlcheck_cb_compatible((expr), _curl_ioctl_callback4))
typedef curlioerr (*_curl_ioctl_callback1)(CURL *, int, void *); typedef curlioerr (*_curl_ioctl_callback1)(CURL *, int, void *);
typedef curlioerr (*_curl_ioctl_callback2)(CURL *, int, const void *); typedef curlioerr (*_curl_ioctl_callback2)(CURL *, int, const void *);
typedef curlioerr (*_curl_ioctl_callback3)(CURL *, curliocmd, void *); typedef curlioerr (*_curl_ioctl_callback3)(CURL *, curliocmd, void *);
typedef curlioerr (*_curl_ioctl_callback4)(CURL *, curliocmd, const void *); typedef curlioerr (*_curl_ioctl_callback4)(CURL *, curliocmd, const void *);
/* evaluates to true if expr is of type curl_sockopt_callback or "similar" */ /* evaluates to true if expr is of type curl_sockopt_callback or "similar" */
#define _curl_is_sockopt_cb(expr) \ #define curlcheck_sockopt_cb(expr) \
(_curl_is_NULL(expr) || \ (curlcheck_NULL(expr) || \
_curl_callback_compatible((expr), curl_sockopt_callback) || \ curlcheck_cb_compatible((expr), curl_sockopt_callback) || \
_curl_callback_compatible((expr), _curl_sockopt_callback1) || \ curlcheck_cb_compatible((expr), _curl_sockopt_callback1) || \
_curl_callback_compatible((expr), _curl_sockopt_callback2)) curlcheck_cb_compatible((expr), _curl_sockopt_callback2))
typedef int (*_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype); typedef int (*_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype);
typedef int (*_curl_sockopt_callback2)(const void *, curl_socket_t, typedef int (*_curl_sockopt_callback2)(const void *, curl_socket_t,
curlsocktype); curlsocktype);
/* evaluates to true if expr is of type curl_opensocket_callback or /* evaluates to true if expr is of type curl_opensocket_callback or
"similar" */ "similar" */
#define _curl_is_opensocket_cb(expr) \ #define curlcheck_opensocket_cb(expr) \
(_curl_is_NULL(expr) || \ (curlcheck_NULL(expr) || \
_curl_callback_compatible((expr), curl_opensocket_callback) || \ curlcheck_cb_compatible((expr), curl_opensocket_callback) || \
_curl_callback_compatible((expr), _curl_opensocket_callback1) || \ curlcheck_cb_compatible((expr), _curl_opensocket_callback1) || \
_curl_callback_compatible((expr), _curl_opensocket_callback2) || \ curlcheck_cb_compatible((expr), _curl_opensocket_callback2) || \
_curl_callback_compatible((expr), _curl_opensocket_callback3) || \ curlcheck_cb_compatible((expr), _curl_opensocket_callback3) || \
_curl_callback_compatible((expr), _curl_opensocket_callback4)) curlcheck_cb_compatible((expr), _curl_opensocket_callback4))
typedef curl_socket_t (*_curl_opensocket_callback1) typedef curl_socket_t (*_curl_opensocket_callback1)
(void *, curlsocktype, struct curl_sockaddr *); (void *, curlsocktype, struct curl_sockaddr *);
typedef curl_socket_t (*_curl_opensocket_callback2) typedef curl_socket_t (*_curl_opensocket_callback2)
@ -595,28 +617,28 @@ typedef curl_socket_t (*_curl_opensocket_callback4)
(const void *, curlsocktype, const struct curl_sockaddr *); (const void *, curlsocktype, const struct curl_sockaddr *);
/* evaluates to true if expr is of type curl_progress_callback or "similar" */ /* evaluates to true if expr is of type curl_progress_callback or "similar" */
#define _curl_is_progress_cb(expr) \ #define curlcheck_progress_cb(expr) \
(_curl_is_NULL(expr) || \ (curlcheck_NULL(expr) || \
_curl_callback_compatible((expr), curl_progress_callback) || \ curlcheck_cb_compatible((expr), curl_progress_callback) || \
_curl_callback_compatible((expr), _curl_progress_callback1) || \ curlcheck_cb_compatible((expr), _curl_progress_callback1) || \
_curl_callback_compatible((expr), _curl_progress_callback2)) curlcheck_cb_compatible((expr), _curl_progress_callback2))
typedef int (*_curl_progress_callback1)(void *, typedef int (*_curl_progress_callback1)(void *,
double, double, double, double); double, double, double, double);
typedef int (*_curl_progress_callback2)(const void *, typedef int (*_curl_progress_callback2)(const void *,
double, double, double, double); double, double, double, double);
/* evaluates to true if expr is of type curl_debug_callback or "similar" */ /* evaluates to true if expr is of type curl_debug_callback or "similar" */
#define _curl_is_debug_cb(expr) \ #define curlcheck_debug_cb(expr) \
(_curl_is_NULL(expr) || \ (curlcheck_NULL(expr) || \
_curl_callback_compatible((expr), curl_debug_callback) || \ curlcheck_cb_compatible((expr), curl_debug_callback) || \
_curl_callback_compatible((expr), _curl_debug_callback1) || \ curlcheck_cb_compatible((expr), _curl_debug_callback1) || \
_curl_callback_compatible((expr), _curl_debug_callback2) || \ curlcheck_cb_compatible((expr), _curl_debug_callback2) || \
_curl_callback_compatible((expr), _curl_debug_callback3) || \ curlcheck_cb_compatible((expr), _curl_debug_callback3) || \
_curl_callback_compatible((expr), _curl_debug_callback4) || \ curlcheck_cb_compatible((expr), _curl_debug_callback4) || \
_curl_callback_compatible((expr), _curl_debug_callback5) || \ curlcheck_cb_compatible((expr), _curl_debug_callback5) || \
_curl_callback_compatible((expr), _curl_debug_callback6) || \ curlcheck_cb_compatible((expr), _curl_debug_callback6) || \
_curl_callback_compatible((expr), _curl_debug_callback7) || \ curlcheck_cb_compatible((expr), _curl_debug_callback7) || \
_curl_callback_compatible((expr), _curl_debug_callback8)) curlcheck_cb_compatible((expr), _curl_debug_callback8))
typedef int (*_curl_debug_callback1) (CURL *, typedef int (*_curl_debug_callback1) (CURL *,
curl_infotype, char *, size_t, void *); curl_infotype, char *, size_t, void *);
typedef int (*_curl_debug_callback2) (CURL *, typedef int (*_curl_debug_callback2) (CURL *,
@ -636,17 +658,17 @@ typedef int (*_curl_debug_callback8) (CURL *,
/* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */ /* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */
/* this is getting even messier... */ /* this is getting even messier... */
#define _curl_is_ssl_ctx_cb(expr) \ #define curlcheck_ssl_ctx_cb(expr) \
(_curl_is_NULL(expr) || \ (curlcheck_NULL(expr) || \
_curl_callback_compatible((expr), curl_ssl_ctx_callback) || \ curlcheck_cb_compatible((expr), curl_ssl_ctx_callback) || \
_curl_callback_compatible((expr), _curl_ssl_ctx_callback1) || \ curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback1) || \
_curl_callback_compatible((expr), _curl_ssl_ctx_callback2) || \ curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback2) || \
_curl_callback_compatible((expr), _curl_ssl_ctx_callback3) || \ curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback3) || \
_curl_callback_compatible((expr), _curl_ssl_ctx_callback4) || \ curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback4) || \
_curl_callback_compatible((expr), _curl_ssl_ctx_callback5) || \ curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback5) || \
_curl_callback_compatible((expr), _curl_ssl_ctx_callback6) || \ curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback6) || \
_curl_callback_compatible((expr), _curl_ssl_ctx_callback7) || \ curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback7) || \
_curl_callback_compatible((expr), _curl_ssl_ctx_callback8)) curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback8))
typedef CURLcode (*_curl_ssl_ctx_callback1)(CURL *, void *, void *); typedef CURLcode (*_curl_ssl_ctx_callback1)(CURL *, void *, void *);
typedef CURLcode (*_curl_ssl_ctx_callback2)(CURL *, void *, const void *); typedef CURLcode (*_curl_ssl_ctx_callback2)(CURL *, void *, const void *);
typedef CURLcode (*_curl_ssl_ctx_callback3)(CURL *, const void *, void *); typedef CURLcode (*_curl_ssl_ctx_callback3)(CURL *, const void *, void *);
@ -656,11 +678,11 @@ typedef CURLcode (*_curl_ssl_ctx_callback4)(CURL *, const void *,
/* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX /* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX
* this will of course break if we're included before OpenSSL headers... * this will of course break if we're included before OpenSSL headers...
*/ */
typedef CURLcode (*_curl_ssl_ctx_callback5)(CURL *, SSL_CTX, void *); typedef CURLcode (*_curl_ssl_ctx_callback5)(CURL *, SSL_CTX *, void *);
typedef CURLcode (*_curl_ssl_ctx_callback6)(CURL *, SSL_CTX, const void *); typedef CURLcode (*_curl_ssl_ctx_callback6)(CURL *, SSL_CTX *, const void *);
typedef CURLcode (*_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX, void *); typedef CURLcode (*_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX *, void *);
typedef CURLcode (*_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX, typedef CURLcode (*_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX *,
const void *); const void *);
#else #else
typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback5; typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback5;
typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback6; typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback6;
@ -669,26 +691,26 @@ typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback8;
#endif #endif
/* evaluates to true if expr is of type curl_conv_callback or "similar" */ /* evaluates to true if expr is of type curl_conv_callback or "similar" */
#define _curl_is_conv_cb(expr) \ #define curlcheck_conv_cb(expr) \
(_curl_is_NULL(expr) || \ (curlcheck_NULL(expr) || \
_curl_callback_compatible((expr), curl_conv_callback) || \ curlcheck_cb_compatible((expr), curl_conv_callback) || \
_curl_callback_compatible((expr), _curl_conv_callback1) || \ curlcheck_cb_compatible((expr), _curl_conv_callback1) || \
_curl_callback_compatible((expr), _curl_conv_callback2) || \ curlcheck_cb_compatible((expr), _curl_conv_callback2) || \
_curl_callback_compatible((expr), _curl_conv_callback3) || \ curlcheck_cb_compatible((expr), _curl_conv_callback3) || \
_curl_callback_compatible((expr), _curl_conv_callback4)) curlcheck_cb_compatible((expr), _curl_conv_callback4))
typedef CURLcode (*_curl_conv_callback1)(char *, size_t length); typedef CURLcode (*_curl_conv_callback1)(char *, size_t length);
typedef CURLcode (*_curl_conv_callback2)(const 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_callback3)(void *, size_t length);
typedef CURLcode (*_curl_conv_callback4)(const 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" */ /* evaluates to true if expr is of type curl_seek_callback or "similar" */
#define _curl_is_seek_cb(expr) \ #define curlcheck_seek_cb(expr) \
(_curl_is_NULL(expr) || \ (curlcheck_NULL(expr) || \
_curl_callback_compatible((expr), curl_seek_callback) || \ curlcheck_cb_compatible((expr), curl_seek_callback) || \
_curl_callback_compatible((expr), _curl_seek_callback1) || \ curlcheck_cb_compatible((expr), _curl_seek_callback1) || \
_curl_callback_compatible((expr), _curl_seek_callback2)) curlcheck_cb_compatible((expr), _curl_seek_callback2))
typedef CURLcode (*_curl_seek_callback1)(void *, curl_off_t, int); typedef CURLcode (*_curl_seek_callback1)(void *, curl_off_t, int);
typedef CURLcode (*_curl_seek_callback2)(const 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 */

View file

@ -1,5 +1,5 @@
#ifndef __CURL_URLAPI_H #ifndef CURLINC_URLAPI_H
#define __CURL_URLAPI_H #define CURLINC_URLAPI_H
/*************************************************************************** /***************************************************************************
* _ _ ____ _ * _ _ ____ _
* Project ___| | | | _ \| | * Project ___| | | | _ \| |
@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2018 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#include "curl.h" #include "curl.h"
@ -47,7 +49,21 @@ typedef enum {
CURLUE_NO_HOST, /* 14 */ CURLUE_NO_HOST, /* 14 */
CURLUE_NO_PORT, /* 15 */ CURLUE_NO_PORT, /* 15 */
CURLUE_NO_QUERY, /* 16 */ CURLUE_NO_QUERY, /* 16 */
CURLUE_NO_FRAGMENT /* 17 */ CURLUE_NO_FRAGMENT, /* 17 */
CURLUE_NO_ZONEID, /* 18 */
CURLUE_BAD_FILE_URL, /* 19 */
CURLUE_BAD_FRAGMENT, /* 20 */
CURLUE_BAD_HOSTNAME, /* 21 */
CURLUE_BAD_IPV6, /* 22 */
CURLUE_BAD_LOGIN, /* 23 */
CURLUE_BAD_PASSWORD, /* 24 */
CURLUE_BAD_PATH, /* 25 */
CURLUE_BAD_QUERY, /* 26 */
CURLUE_BAD_SCHEME, /* 27 */
CURLUE_BAD_SLASHES, /* 28 */
CURLUE_BAD_USER, /* 29 */
CURLUE_LACKS_IDN, /* 30 */
CURLUE_LAST
} CURLUcode; } CURLUcode;
typedef enum { typedef enum {
@ -77,6 +93,10 @@ typedef enum {
#define CURLU_URLENCODE (1<<7) /* URL encode on set */ #define CURLU_URLENCODE (1<<7) /* URL encode on set */
#define CURLU_APPENDQUERY (1<<8) /* append a form style part */ #define CURLU_APPENDQUERY (1<<8) /* append a form style part */
#define CURLU_GUESS_SCHEME (1<<9) /* legacy curl-style guessing */ #define CURLU_GUESS_SCHEME (1<<9) /* legacy curl-style guessing */
#define CURLU_NO_AUTHORITY (1<<10) /* Allow empty authority when the
scheme is unknown. */
#define CURLU_ALLOW_SPACE (1<<11) /* Allow spaces in the URL */
#define CURLU_PUNYCODE (1<<12) /* get the host name in pynycode */
typedef struct Curl_URL CURLU; typedef struct Curl_URL CURLU;
@ -97,14 +117,14 @@ CURL_EXTERN void curl_url_cleanup(CURLU *handle);
* curl_url_dup() duplicates a CURLU handle and returns a new copy. The new * curl_url_dup() duplicates a CURLU handle and returns a new copy. The new
* handle must also be freed with curl_url_cleanup(). * handle must also be freed with curl_url_cleanup().
*/ */
CURL_EXTERN CURLU *curl_url_dup(CURLU *in); CURL_EXTERN CURLU *curl_url_dup(const CURLU *in);
/* /*
* curl_url_get() extracts a specific part of the URL from a CURLU * curl_url_get() extracts a specific part of the URL from a CURLU
* handle. Returns error code. The returned pointer MUST be freed with * handle. Returns error code. The returned pointer MUST be freed with
* curl_free() afterwards. * curl_free() afterwards.
*/ */
CURL_EXTERN CURLUcode curl_url_get(CURLU *handle, CURLUPart what, CURL_EXTERN CURLUcode curl_url_get(const CURLU *handle, CURLUPart what,
char **part, unsigned int flags); char **part, unsigned int flags);
/* /*
@ -115,9 +135,15 @@ CURL_EXTERN CURLUcode curl_url_get(CURLU *handle, CURLUPart what,
CURL_EXTERN CURLUcode curl_url_set(CURLU *handle, CURLUPart what, CURL_EXTERN CURLUcode curl_url_set(CURLU *handle, CURLUPart what,
const char *part, unsigned int flags); const char *part, unsigned int flags);
/*
* curl_url_strerror() turns a CURLUcode value into the equivalent human
* readable error string. This is useful for printing meaningful error
* messages.
*/
CURL_EXTERN const char *curl_url_strerror(CURLUcode);
#ifdef __cplusplus #ifdef __cplusplus
} /* end of extern "C" */ } /* end of extern "C" */
#endif #endif
#endif #endif /* CURLINC_URLAPI_H */

View file

@ -0,0 +1,84 @@
#ifndef CURLINC_WEBSOCKETS_H
#define CURLINC_WEBSOCKETS_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
struct curl_ws_frame {
int age; /* zero */
int flags; /* See the CURLWS_* defines */
curl_off_t offset; /* the offset of this data into the frame */
curl_off_t bytesleft; /* number of pending bytes left of the payload */
size_t len; /* size of the current data chunk */
};
/* flag bits */
#define CURLWS_TEXT (1<<0)
#define CURLWS_BINARY (1<<1)
#define CURLWS_CONT (1<<2)
#define CURLWS_CLOSE (1<<3)
#define CURLWS_PING (1<<4)
#define CURLWS_OFFSET (1<<5)
/*
* NAME curl_ws_recv()
*
* DESCRIPTION
*
* Receives data from the websocket connection. Use after successful
* curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
*/
CURL_EXTERN CURLcode curl_ws_recv(CURL *curl, void *buffer, size_t buflen,
size_t *recv,
struct curl_ws_frame **metap);
/* sendflags for curl_ws_send() */
#define CURLWS_PONG (1<<6)
/*
* NAME curl_easy_send()
*
* DESCRIPTION
*
* Sends data over the websocket connection. Use after successful
* curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
*/
CURL_EXTERN CURLcode curl_ws_send(CURL *curl, const void *buffer,
size_t buflen, size_t *sent,
curl_off_t framesize,
unsigned int sendflags);
/* bits for the CURLOPT_WS_OPTIONS bitmask: */
#define CURLWS_RAW_MODE (1<<0)
CURL_EXTERN struct curl_ws_frame *curl_ws_meta(CURL *curl);
#ifdef __cplusplus
}
#endif
#endif /* CURLINC_WEBSOCKETS_H */

View file

@ -1,4 +1,29 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
set(LIB_NAME cmcurl) set(LIB_NAME cmcurl)
set(LIBCURL_OUTPUT_NAME cmcurl)
add_definitions(-DBUILDING_LIBCURL)
if(BUILD_SHARED_LIBS) if(BUILD_SHARED_LIBS)
set(CURL_STATICLIB NO) set(CURL_STATICLIB NO)
@ -18,43 +43,10 @@ list(APPEND HHEADERS
${CMAKE_CURRENT_BINARY_DIR}/curl_config.h ${CMAKE_CURRENT_BINARY_DIR}/curl_config.h
) )
if(MSVC AND NOT CURL_STATICLIB) if(WIN32 AND NOT CURL_STATICLIB)
list(APPEND CSOURCES libcurl.rc) list(APPEND CSOURCES libcurl.rc)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4127")
endif() endif()
# SET(CSOURCES
# # memdebug.c -not used
# # nwlib.c - Not used
# # strtok.c - specify later
# # strtoofft.c - specify later
# )
# # if we have Kerberos 4, right now this is never on
# #OPTION(CURL_KRB4 "Use Kerberos 4" OFF)
# IF(CURL_KRB4)
# SET(CSOURCES ${CSOURCES}
# krb4.c
# security.c
# )
# ENDIF(CURL_KRB4)
# #OPTION(CURL_MALLOC_DEBUG "Debug mallocs in Curl" OFF)
# MARK_AS_ADVANCED(CURL_MALLOC_DEBUG)
# IF(CURL_MALLOC_DEBUG)
# SET(CSOURCES ${CSOURCES}
# memdebug.c
# )
# ENDIF(CURL_MALLOC_DEBUG)
# # only build compat strtoofft if we need to
# IF(NOT HAVE_STRTOLL AND NOT HAVE__STRTOI64)
# SET(CSOURCES ${CSOURCES}
# strtoofft.c
# )
# ENDIF(NOT HAVE_STRTOLL AND NOT HAVE__STRTOI64)
# The rest of the build # The rest of the build
include_directories(${CMAKE_CURRENT_BINARY_DIR}/../include) include_directories(${CMAKE_CURRENT_BINARY_DIR}/../include)
@ -70,7 +62,7 @@ endif()
# For windows we want to install OPENSSL_LIBRARIES dlls # For windows we want to install OPENSSL_LIBRARIES dlls
# and also copy them into the build tree so that testing # and also copy them into the build tree so that testing
# can find them. # can find them.
if(CMAKE_USE_OPENSSL AND OPENSSL_FOUND AND WIN32) if(CURL_USE_OPENSSL AND OPENSSL_FOUND AND WIN32)
find_file(CMAKE_EAY_DLL NAME libeay32.dll HINTS ${OPENSSL_INCLUDE_DIR}/..) find_file(CMAKE_EAY_DLL NAME libeay32.dll HINTS ${OPENSSL_INCLUDE_DIR}/..)
find_file(CMAKE_SSL_DLL NAME ssleay32.dll HINTS ${OPENSSL_INCLUDE_DIR}/..) find_file(CMAKE_SSL_DLL NAME ssleay32.dll HINTS ${OPENSSL_INCLUDE_DIR}/..)
mark_as_advanced(CMAKE_EAY_DLL CMAKE_SSL_DLL) mark_as_advanced(CMAKE_EAY_DLL CMAKE_SSL_DLL)
@ -97,21 +89,52 @@ add_library(
${CMAKE_CURL_SSL_DLLS} ${CMAKE_CURL_SSL_DLLS}
) )
add_library(
${PROJECT_NAME}::${LIB_NAME}
ALIAS ${LIB_NAME}
)
if(NOT BUILD_SHARED_LIBS) if(NOT BUILD_SHARED_LIBS)
set_target_properties(${LIB_NAME} PROPERTIES INTERFACE_COMPILE_DEFINITIONS CURL_STATICLIB) set_target_properties(${LIB_NAME} PROPERTIES INTERFACE_COMPILE_DEFINITIONS CURL_STATICLIB)
endif() endif()
target_link_libraries(${LIB_NAME} ${CURL_LIBS}) target_link_libraries(${LIB_NAME} PRIVATE ${CURL_LIBS})
if(0) # This code not needed for building within CMake. if(0) # This code not needed for building within CMake.
if(WIN32) transform_makefile_inc("Makefile.soname" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake")
add_definitions(-D_USRDLL) include(${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake)
endif()
endif() endif()
set_target_properties(${LIB_NAME} PROPERTIES COMPILE_DEFINITIONS BUILDING_LIBCURL) set_target_properties(${LIB_NAME} PROPERTIES
COMPILE_DEFINITIONS BUILDING_LIBCURL
OUTPUT_NAME ${LIBCURL_OUTPUT_NAME}
)
if(0) # This code not needed for building within CMake. if(0) # This code not needed for building within CMake.
if(CMAKE_SYSTEM_NAME STREQUAL "AIX" OR
CMAKE_SYSTEM_NAME STREQUAL "Linux" OR
CMAKE_SYSTEM_NAME STREQUAL "Darwin" OR
CMAKE_SYSTEM_NAME STREQUAL "GNU/kFreeBSD" OR
# FreeBSD comes with the a.out and elf flavours
# but a.out was supported up to version 3.x and
# elf from 3.x. I cannot imagine someone running
# CMake on those ancient systems
CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR
CMAKE_SYSTEM_NAME STREQUAL "Haiku")
math(EXPR CMAKESONAME "${VERSIONCHANGE} - ${VERSIONDEL}")
set(CMAKEVERSION "${CMAKESONAME}.${VERSIONDEL}.${VERSIONADD}")
set_target_properties(${LIB_NAME} PROPERTIES
VERSION ${CMAKEVERSION}
SOVERSION ${CMAKESONAME}
)
endif()
if(HIDES_CURL_PRIVATE_SYMBOLS) if(HIDES_CURL_PRIVATE_SYMBOLS)
set_property(TARGET ${LIB_NAME} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS") set_property(TARGET ${LIB_NAME} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS")
set_property(TARGET ${LIB_NAME} APPEND PROPERTY COMPILE_FLAGS ${CURL_CFLAG_SYMBOLS_HIDE}) set_property(TARGET ${LIB_NAME} APPEND PROPERTY COMPILE_FLAGS ${CURL_CFLAG_SYMBOLS_HIDE})
@ -121,27 +144,38 @@ endif()
set_target_properties(${LIB_NAME} PROPERTIES PREFIX "") set_target_properties(${LIB_NAME} PROPERTIES PREFIX "")
set_target_properties(${LIB_NAME} PROPERTIES IMPORT_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(WIN32)
if(BUILD_SHARED_LIBS) if(BUILD_SHARED_LIBS)
# Add "_imp" as a suffix before the extension to avoid conflicting with the statically linked "libcurl.lib" if(MSVC)
set_target_properties(${LIB_NAME} PROPERTIES IMPORT_SUFFIX "_imp.lib") # Add "_imp" as a suffix before the extension to avoid conflicting with
# the statically linked "libcurl.lib"
set_target_properties(${LIB_NAME} PROPERTIES IMPORT_SUFFIX "_imp.lib")
endif()
endif() endif()
endif() endif()
target_include_directories(${LIB_NAME} INTERFACE target_include_directories(${LIB_NAME} INTERFACE
$<INSTALL_INTERFACE:include> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
$<BUILD_INTERFACE:${CURL_SOURCE_DIR}/include>) $<BUILD_INTERFACE:${CURL_SOURCE_DIR}/include>)
install(TARGETS ${LIB_NAME} if(CURL_ENABLE_EXPORT_TARGET)
EXPORT ${TARGETS_EXPORT_NAME} install(TARGETS ${LIB_NAME}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT ${TARGETS_EXPORT_NAME}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
) RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
export(TARGETS ${LIB_NAME} export(TARGETS ${LIB_NAME}
APPEND FILE ${PROJECT_BINARY_DIR}/libcurl-target.cmake FILE ${PROJECT_BINARY_DIR}/libcurl-target.cmake
NAMESPACE CURL:: NAMESPACE ${PROJECT_NAME}::
) )
endif()
endif() endif()

View file

@ -5,11 +5,11 @@
# | (__| |_| | _ <| |___ # | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____| # \___|\___/|_| \_\_____|
# #
# Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. # Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
# #
# This software is licensed as described in the file COPYING, which # This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms # you should have received as part of this distribution. The terms
# are also available at https://curl.haxx.se/docs/copyright.html. # are also available at https://curl.se/docs/copyright.html.
# #
# You may opt to use, copy, modify, merge, publish, distribute and/or sell # You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is # copies of the Software, and permit persons to whom the Software is
@ -18,67 +18,344 @@
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY # This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied. # KIND, either express or implied.
# #
# SPDX-License-Identifier: curl
#
########################################################################### ###########################################################################
LIB_VAUTH_CFILES = vauth/vauth.c vauth/cleartext.c vauth/cram.c \ LIB_VAUTH_CFILES = \
vauth/digest.c vauth/digest_sspi.c vauth/krb5_gssapi.c \ vauth/cleartext.c \
vauth/krb5_sspi.c vauth/ntlm.c vauth/ntlm_sspi.c vauth/oauth2.c \ vauth/cram.c \
vauth/spnego_gssapi.c vauth/spnego_sspi.c vauth/digest.c \
vauth/digest_sspi.c \
vauth/gsasl.c \
vauth/krb5_gssapi.c \
vauth/krb5_sspi.c \
vauth/ntlm.c \
vauth/ntlm_sspi.c \
vauth/oauth2.c \
vauth/spnego_gssapi.c \
vauth/spnego_sspi.c \
vauth/vauth.c
LIB_VAUTH_HFILES = vauth/vauth.h vauth/digest.h vauth/ntlm.h LIB_VAUTH_HFILES = \
vauth/digest.h \
vauth/ntlm.h \
vauth/vauth.h
LIB_VTLS_CFILES = vtls/openssl.c vtls/gtls.c vtls/vtls.c vtls/nss.c \ LIB_VTLS_CFILES = \
vtls/polarssl.c vtls/polarssl_threadlock.c \ vtls/bearssl.c \
vtls/cyassl.c vtls/schannel.c vtls/schannel_verify.c \ vtls/gskit.c \
vtls/sectransp.c vtls/gskit.c vtls/mbedtls.c vtls/mesalink.c vtls/gtls.c \
vtls/hostcheck.c \
vtls/keylog.c \
vtls/mbedtls.c \
vtls/mbedtls_threadlock.c \
vtls/nss.c \
vtls/openssl.c \
vtls/rustls.c \
vtls/schannel.c \
vtls/schannel_verify.c \
vtls/sectransp.c \
vtls/vtls.c \
vtls/wolfssl.c \
vtls/x509asn1.c
LIB_VTLS_HFILES = vtls/openssl.h vtls/vtls.h vtls/gtls.h \ LIB_VTLS_HFILES = \
vtls/nssg.h vtls/polarssl.h vtls/polarssl_threadlock.h \ vtls/bearssl.h \
vtls/cyassl.h vtls/schannel.h vtls/sectransp.h vtls/gskit.h \ vtls/gskit.h \
vtls/mbedtls.h vtls/mesalink.h vtls/gtls.h \
vtls/hostcheck.h \
vtls/keylog.h \
vtls/mbedtls.h \
vtls/mbedtls_threadlock.h \
vtls/nssg.h \
vtls/openssl.h \
vtls/rustls.h \
vtls/schannel.h \
vtls/sectransp.h \
vtls/vtls.h \
vtls/vtls_int.h \
vtls/wolfssl.h \
vtls/x509asn1.h
LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c \ LIB_VQUIC_CFILES = \
cookie.c http.c sendf.c ftp.c url.c dict.c if2ip.c speedcheck.c \ vquic/curl_msh3.c \
ldap.c version.c getenv.c escape.c mprintf.c telnet.c netrc.c \ vquic/curl_ngtcp2.c \
getinfo.c transfer.c strcase.c easy.c security.c curl_fnmatch.c \ vquic/curl_quiche.c \
fileinfo.c ftplistparser.c wildcard.c krb5.c memdebug.c http_chunks.c \ vquic/vquic.c
strtok.c connect.c llist.c hash.c multi.c content_encoding.c share.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_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 \
http_proxy.c non-ascii.c asyn-ares.c asyn-thread.c curl_gssapi.c \
http_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c curl_sasl.c rand.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
LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \ LIB_VQUIC_HFILES = \
formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h if2ip.h \ vquic/curl_msh3.h \
speedcheck.h urldata.h curl_ldap.h escape.h telnet.h getinfo.h \ vquic/curl_ngtcp2.h \
strcase.h curl_sec.h memdebug.h http_chunks.h curl_fnmatch.h \ vquic/curl_quiche.h \
wildcard.h fileinfo.h ftplistparser.h strtok.h connect.h llist.h \ vquic/vquic.h \
hash.h content_encoding.h share.h curl_md4.h curl_md5.h http_digest.h \ vquic/vquic_int.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 \ LIB_VSSH_CFILES = \
easyif.h multiif.h parsedate.h tftp.h sockaddr.h splay.h strdup.h \ vssh/libssh.c \
socks.h ssh.h curl_base64.h curl_addrinfo.h curl_sspi.h \ vssh/libssh2.c \
slist.h nonblock.h curl_memrchr.h imap.h pop3.h smtp.h pingpong.h \ vssh/wolfssh.c
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 \ LIB_VSSH_HFILES = \
http_ntlm.h curl_gssapi.h curl_ntlm_wb.h curl_ntlm_core.h \ vssh/ssh.h
curl_sasl.h curl_multibyte.h hostcheck.h conncache.h \
curl_setup_once.h multihandle.h setup-vms.h dotdot.h \ LIB_CFILES = \
x509asn1.h http2.h sigpipe.h smb.h curl_endian.h curl_des.h \ altsvc.c \
curl_printf.h system_win32.h rand.h mime.h curl_sha256.h setopt.h \ amigaos.c \
curl_path.h curl_ctype.h curl_range.h psl.h doh.h urlapi-int.h \ asyn-ares.c \
curl_get_line.h altsvc.h asyn-thread.c \
base64.c \
bufref.c \
c-hyper.c \
cf-https-connect.c \
cf-socket.c \
cfilters.c \
conncache.c \
connect.c \
content_encoding.c \
cookie.c \
curl_addrinfo.c \
curl_des.c \
curl_endian.c \
curl_fnmatch.c \
curl_get_line.c \
curl_gethostname.c \
curl_gssapi.c \
curl_log.c \
curl_memrchr.c \
curl_multibyte.c \
curl_ntlm_core.c \
curl_ntlm_wb.c \
curl_path.c \
curl_range.c \
curl_rtmp.c \
curl_sasl.c \
curl_sspi.c \
curl_threads.c \
dict.c \
doh.c \
dynbuf.c \
easy.c \
easygetopt.c \
easyoptions.c \
escape.c \
file.c \
fileinfo.c \
fopen.c \
formdata.c \
ftp.c \
ftplistparser.c \
getenv.c \
getinfo.c \
gopher.c \
h2h3.c \
hash.c \
headers.c \
hmac.c \
hostasyn.c \
hostip.c \
hostip4.c \
hostip6.c \
hostsyn.c \
hsts.c \
http.c \
http2.c \
http_chunks.c \
http_digest.c \
http_negotiate.c \
http_ntlm.c \
http_proxy.c \
http_aws_sigv4.c \
idn.c \
if2ip.c \
imap.c \
inet_ntop.c \
inet_pton.c \
krb5.c \
ldap.c \
llist.c \
md4.c \
md5.c \
memdebug.c \
mime.c \
mprintf.c \
mqtt.c \
multi.c \
netrc.c \
nonblock.c \
noproxy.c \
openldap.c \
parsedate.c \
pingpong.c \
pop3.c \
progress.c \
psl.c \
rand.c \
rename.c \
rtsp.c \
select.c \
sendf.c \
setopt.c \
sha256.c \
share.c \
slist.c \
smb.c \
smtp.c \
socketpair.c \
socks.c \
socks_gssapi.c \
socks_sspi.c \
speedcheck.c \
splay.c \
strcase.c \
strdup.c \
strerror.c \
strtok.c \
strtoofft.c \
system_win32.c \
telnet.c \
tftp.c \
timediff.c \
timeval.c \
transfer.c \
url.c \
urlapi.c \
version.c \
version_win32.c \
warnless.c \
ws.c
LIB_HFILES = \
altsvc.h \
amigaos.h \
arpa_telnet.h \
asyn.h \
bufref.h \
c-hyper.h \
cf-https-connect.h \
cf-socket.h \
cfilters.h \
conncache.h \
connect.h \
content_encoding.h \
cookie.h \
curl_addrinfo.h \
curl_base64.h \
curl_ctype.h \
curl_des.h \
curl_endian.h \
curl_fnmatch.h \
curl_get_line.h \
curl_gethostname.h \
curl_gssapi.h \
curl_hmac.h \
curl_krb5.h \
curl_ldap.h \
curl_log.h \
curl_md4.h \
curl_md5.h \
curl_memory.h \
curl_memrchr.h \
curl_multibyte.h \
curl_ntlm_core.h \
curl_ntlm_wb.h \
curl_path.h \
curl_printf.h \
curl_range.h \
curl_rtmp.h \
curl_sasl.h \
curl_setup.h \
curl_setup_once.h \
curl_sha256.h \
curl_sspi.h \
curl_threads.h \
curlx.h \
dict.h \
doh.h \
dynbuf.h \
easy_lock.h \
easyif.h \
easyoptions.h \
escape.h \
file.h \
fileinfo.h \
fopen.h \
formdata.h \
functypes.h \
ftp.h \
ftplistparser.h \
getinfo.h \
gopher.h \
h2h3.h \
hash.h \
headers.h \
hostip.h \
hsts.h \
http.h \
http2.h \
http_chunks.h \
http_digest.h \
http_negotiate.h \
http_ntlm.h \
http_proxy.h \
http_aws_sigv4.h \
idn.h \
if2ip.h \
imap.h \
inet_ntop.h \
inet_pton.h \
llist.h \
memdebug.h \
mime.h \
mqtt.h \
multihandle.h \
multiif.h \
netrc.h \
nonblock.h \
noproxy.h \
parsedate.h \
pingpong.h \
pop3.h \
progress.h \
psl.h \
rand.h \
rename.h \
rtsp.h \
select.h \
sendf.h \
setopt.h \
setup-vms.h \
share.h \
sigpipe.h \
slist.h \
smb.h \
smtp.h \
sockaddr.h \
socketpair.h \
socks.h \
speedcheck.h \
splay.h \
strcase.h \
strdup.h \
strerror.h \
strtok.h \
strtoofft.h \
system_win32.h \
telnet.h \
tftp.h \
timediff.h \
timeval.h \
transfer.h \
url.h \
urlapi-int.h \
urldata.h \
version_win32.h \
warnless.h \
ws.h
LIB_RCFILES = libcurl.rc LIB_RCFILES = libcurl.rc
CSOURCES = $(LIB_CFILES) $(LIB_VAUTH_CFILES) $(LIB_VTLS_CFILES) CSOURCES = $(LIB_CFILES) $(LIB_VAUTH_CFILES) $(LIB_VTLS_CFILES) \
HHEADERS = $(LIB_HFILES) $(LIB_VAUTH_HFILES) $(LIB_VTLS_HFILES) $(LIB_VQUIC_CFILES) $(LIB_VSSH_CFILES)
HHEADERS = $(LIB_HFILES) $(LIB_VAUTH_HFILES) $(LIB_VTLS_HFILES) \
$(LIB_VQUIC_HFILES) $(LIB_VSSH_HFILES)

View file

@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -18,14 +18,16 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
/* /*
* The Alt-Svc: header is defined in RFC 7838: * The Alt-Svc: header is defined in RFC 7838:
* https://tools.ietf.org/html/rfc7838 * https://datatracker.ietf.org/doc/html/rfc7838
*/ */
#include "curl_setup.h" #include "curl_setup.h"
#if !defined(CURL_DISABLE_HTTP) && defined(USE_ALTSVC) #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_ALTSVC)
#include <curl/curl.h> #include <curl/curl.h>
#include "urldata.h" #include "urldata.h"
#include "altsvc.h" #include "altsvc.h"
@ -34,6 +36,8 @@
#include "parsedate.h" #include "parsedate.h"
#include "sendf.h" #include "sendf.h"
#include "warnless.h" #include "warnless.h"
#include "fopen.h"
#include "rename.h"
/* The last 3 #include files should be in this order */ /* The last 3 #include files should be in this order */
#include "curl_printf.h" #include "curl_printf.h"
@ -48,15 +52,15 @@
#define MAX_ALTSVC_ALPNLENSTR "10" #define MAX_ALTSVC_ALPNLENSTR "10"
#define MAX_ALTSVC_ALPNLEN 10 #define MAX_ALTSVC_ALPNLEN 10
#define H3VERSION "h3"
static enum alpnid alpn2alpnid(char *name) static enum alpnid alpn2alpnid(char *name)
{ {
if(strcasecompare(name, "h1")) if(strcasecompare(name, "h1"))
return ALPN_h1; return ALPN_h1;
if(strcasecompare(name, "h2")) if(strcasecompare(name, "h2"))
return ALPN_h2; return ALPN_h2;
if(strcasecompare(name, "h2c")) if(strcasecompare(name, H3VERSION))
return ALPN_h2c;
if(strcasecompare(name, "h3"))
return ALPN_h3; return ALPN_h3;
return ALPN_none; /* unknown, probably rubbish input */ return ALPN_none; /* unknown, probably rubbish input */
} }
@ -69,10 +73,8 @@ const char *Curl_alpnid2str(enum alpnid id)
return "h1"; return "h1";
case ALPN_h2: case ALPN_h2:
return "h2"; return "h2";
case ALPN_h2c:
return "h2c";
case ALPN_h3: case ALPN_h3:
return "h3"; return H3VERSION;
default: default:
return ""; /* bad */ return ""; /* bad */
} }
@ -81,8 +83,8 @@ const char *Curl_alpnid2str(enum alpnid id)
static void altsvc_free(struct altsvc *as) static void altsvc_free(struct altsvc *as)
{ {
free(as->srchost); free(as->src.host);
free(as->dsthost); free(as->dst.host);
free(as); free(as);
} }
@ -94,20 +96,25 @@ static struct altsvc *altsvc_createid(const char *srchost,
unsigned int dstport) unsigned int dstport)
{ {
struct altsvc *as = calloc(sizeof(struct altsvc), 1); struct altsvc *as = calloc(sizeof(struct altsvc), 1);
size_t hlen;
if(!as) if(!as)
return NULL; return NULL;
hlen = strlen(srchost);
as->srchost = strdup(srchost); DEBUGASSERT(hlen);
if(!as->srchost) as->src.host = strdup(srchost);
if(!as->src.host)
goto error; goto error;
as->dsthost = strdup(dsthost); if(hlen && (srchost[hlen - 1] == '.'))
if(!as->dsthost) /* strip off trailing any dot */
as->src.host[--hlen] = 0;
as->dst.host = strdup(dsthost);
if(!as->dst.host)
goto error; goto error;
as->srcalpnid = srcalpnid; as->src.alpnid = srcalpnid;
as->dstalpnid = dstalpnid; as->dst.alpnid = dstalpnid;
as->srcport = curlx_ultous(srcport); as->src.port = curlx_ultous(srcport);
as->dstport = curlx_ultous(dstport); as->dst.port = curlx_ultous(dstport);
return as; return as;
error: error:
@ -156,14 +163,13 @@ static CURLcode altsvc_add(struct altsvcinfo *asi, char *line)
date, &persist, &prio); date, &persist, &prio);
if(9 == rc) { if(9 == rc) {
struct altsvc *as; 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); as = altsvc_create(srchost, dsthost, srcalpn, dstalpn, srcport, dstport);
if(as) { if(as) {
as->expires = expires; as->expires = expires;
as->prio = prio; as->prio = prio;
as->persist = persist ? 1 : 0; as->persist = persist ? 1 : 0;
Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node); Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node);
asi->num++; /* one more entry */
} }
} }
@ -172,10 +178,9 @@ static CURLcode altsvc_add(struct altsvcinfo *asi, char *line)
/* /*
* Load alt-svc entries from the given file. The text based line-oriented file * Load alt-svc entries from the given file. The text based line-oriented file
* format is documented here: * format is documented here: https://curl.se/docs/alt-svc.html
* https://github.com/curl/curl/wiki/QUIC-implementation
* *
* This function only returns error on major problems that prevents alt-svc * This function only returns error on major problems that prevent alt-svc
* handling to work completely. It will ignore individual syntactical errors * handling to work completely. It will ignore individual syntactical errors
* etc. * etc.
*/ */
@ -183,7 +188,16 @@ static CURLcode altsvc_load(struct altsvcinfo *asi, const char *file)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
char *line = NULL; 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) { if(fp) {
line = malloc(MAX_ALTSVC_LINE); line = malloc(MAX_ALTSVC_LINE);
if(!line) if(!line)
@ -204,6 +218,7 @@ static CURLcode altsvc_load(struct altsvcinfo *asi, const char *file)
return result; return result;
fail: fail:
Curl_safefree(asi->filename);
free(line); free(line);
fclose(fp); fclose(fp);
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
@ -226,8 +241,8 @@ static CURLcode altsvc_out(struct altsvc *as, FILE *fp)
"\"%d%02d%02d " "\"%d%02d%02d "
"%02d:%02d:%02d\" " "%02d:%02d:%02d\" "
"%u %d\n", "%u %d\n",
Curl_alpnid2str(as->srcalpnid), as->srchost, as->srcport, Curl_alpnid2str(as->src.alpnid), as->src.host, as->src.port,
Curl_alpnid2str(as->dstalpnid), as->dsthost, as->dstport, Curl_alpnid2str(as->dst.alpnid), as->dst.host, as->dst.port,
stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday, stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday,
stamp.tm_hour, stamp.tm_min, stamp.tm_sec, stamp.tm_hour, stamp.tm_min, stamp.tm_sec,
as->persist, as->prio); as->persist, as->prio);
@ -249,10 +264,10 @@ struct altsvcinfo *Curl_altsvc_init(void)
/* set default behavior */ /* set default behavior */
asi->flags = CURLALTSVC_H1 asi->flags = CURLALTSVC_H1
#ifdef USE_NGHTTP2 #ifdef USE_HTTP2
| CURLALTSVC_H2 | CURLALTSVC_H2
#endif #endif
#ifdef USE_HTTP3 #ifdef ENABLE_QUIC
| CURLALTSVC_H3 | CURLALTSVC_H3
#endif #endif
; ;
@ -287,51 +302,67 @@ CURLcode Curl_altsvc_ctrl(struct altsvcinfo *asi, const long ctrl)
* Curl_altsvc_cleanup() frees an altsvc cache instance and all associated * Curl_altsvc_cleanup() frees an altsvc cache instance and all associated
* resources. * resources.
*/ */
void Curl_altsvc_cleanup(struct altsvcinfo *altsvc) void Curl_altsvc_cleanup(struct altsvcinfo **altsvcp)
{ {
struct curl_llist_element *e; struct Curl_llist_element *e;
struct curl_llist_element *n; struct Curl_llist_element *n;
if(altsvc) { if(*altsvcp) {
struct altsvcinfo *altsvc = *altsvcp;
for(e = altsvc->list.head; e; e = n) { for(e = altsvc->list.head; e; e = n) {
struct altsvc *as = e->ptr; struct altsvc *as = e->ptr;
n = e->next; n = e->next;
altsvc_free(as); altsvc_free(as);
} }
free(altsvc->filename);
free(altsvc); free(altsvc);
*altsvcp = NULL; /* clear the pointer */
} }
} }
/* /*
* Curl_altsvc_save() writes the altsvc cache to a file. * 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 *e;
struct curl_llist_element *n; struct Curl_llist_element *n;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
FILE *out; FILE *out;
char *tempstore = NULL;
if(!altsvc) if(!altsvc)
/* no cache activated */ /* no cache activated */
return CURLE_OK; return CURLE_OK;
if((altsvc->flags & CURLALTSVC_READONLYFILE) || !file[0]) /* if not new name is given, use the one we stored from the load */
/* marked as read-only or zero length file name */ 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; return CURLE_OK;
out = fopen(file, FOPEN_WRITETEXT);
if(!out) result = Curl_fopen(data, file, &out, &tempstore);
return CURLE_WRITE_ERROR; if(!result) {
fputs("# Your alt-svc cache. https://curl.haxx.se/docs/alt-svc.html\n" fputs("# Your alt-svc cache. https://curl.se/docs/alt-svc.html\n"
"# This file was generated by libcurl! Edit at your own risk.\n", "# This file was generated by libcurl! Edit at your own risk.\n",
out); out);
for(e = altsvc->list.head; e; e = n) { for(e = altsvc->list.head; e; e = n) {
struct altsvc *as = e->ptr; struct altsvc *as = e->ptr;
n = e->next; n = e->next;
result = altsvc_out(as, out); result = altsvc_out(as, out);
if(result) if(result)
break; break;
}
fclose(out);
if(!result && tempstore && Curl_rename(tempstore, file))
result = CURLE_WRITE_ERROR;
if(result && tempstore)
unlink(tempstore);
} }
fclose(out); free(tempstore);
return result; return result;
} }
@ -343,34 +374,49 @@ static CURLcode getalnum(const char **ptr, char *alpnbuf, size_t buflen)
while(*p && ISBLANK(*p)) while(*p && ISBLANK(*p))
p++; p++;
protop = p; protop = p;
while(*p && ISALNUM(*p)) while(*p && !ISBLANK(*p) && (*p != ';') && (*p != '='))
p++; p++;
len = p - protop; len = p - protop;
*ptr = p;
if(!len || (len >= buflen)) if(!len || (len >= buflen))
return CURLE_BAD_FUNCTION_ARGUMENT; return CURLE_BAD_FUNCTION_ARGUMENT;
memcpy(alpnbuf, protop, len); memcpy(alpnbuf, protop, len);
alpnbuf[len] = 0; alpnbuf[len] = 0;
*ptr = p;
return CURLE_OK; return CURLE_OK;
} }
/* hostcompare() returns true if 'host' matches 'check'. The first host
* argument may have a trailing dot present that will be ignored.
*/
static bool hostcompare(const char *host, const char *check)
{
size_t hlen = strlen(host);
size_t clen = strlen(check);
if(hlen && (host[hlen - 1] == '.'))
hlen--;
if(hlen != clen)
/* they can't match if they have different lengths */
return FALSE;
return strncasecompare(host, check, hlen);
}
/* altsvc_flush() removes all alternatives for this source origin from the /* altsvc_flush() removes all alternatives for this source origin from the
list */ list */
static void altsvc_flush(struct altsvcinfo *asi, enum alpnid srcalpnid, static void altsvc_flush(struct altsvcinfo *asi, enum alpnid srcalpnid,
const char *srchost, unsigned short srcport) const char *srchost, unsigned short srcport)
{ {
struct curl_llist_element *e; struct Curl_llist_element *e;
struct curl_llist_element *n; struct Curl_llist_element *n;
for(e = asi->list.head; e; e = n) { for(e = asi->list.head; e; e = n) {
struct altsvc *as = e->ptr; struct altsvc *as = e->ptr;
n = e->next; n = e->next;
if((srcalpnid == as->srcalpnid) && if((srcalpnid == as->src.alpnid) &&
(srcport == as->srcport) && (srcport == as->src.port) &&
strcasecompare(srchost, as->srchost)) { hostcompare(srchost, as->src.host)) {
Curl_llist_remove(&asi->list, e, NULL); Curl_llist_remove(&asi->list, e, NULL);
altsvc_free(as); altsvc_free(as);
asi->num--;
} }
} }
} }
@ -391,12 +437,18 @@ static time_t debugtime(void *unused)
#define time(x) debugtime(x) #define time(x) debugtime(x)
#endif #endif
#define ISNEWLINE(x) (((x) == '\n') || (x) == '\r')
/* /*
* Curl_altsvc_parse() takes an incoming alt-svc response header and stores * Curl_altsvc_parse() takes an incoming alt-svc response header and stores
* the data correctly in the cache. * the data correctly in the cache.
* *
* 'value' points to the header *value*. That's contents to the right of the * 'value' points to the header *value*. That's contents to the right of the
* header name. * 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, CURLcode Curl_altsvc_parse(struct Curl_easy *data,
struct altsvcinfo *asi, const char *value, struct altsvcinfo *asi, const char *value,
@ -405,69 +457,44 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
{ {
const char *p = value; const char *p = value;
size_t len; size_t len;
enum alpnid dstalpnid = srcalpnid; /* the same by default */
char namebuf[MAX_ALTSVC_HOSTLEN] = ""; char namebuf[MAX_ALTSVC_HOSTLEN] = "";
char alpnbuf[MAX_ALTSVC_ALPNLEN] = ""; char alpnbuf[MAX_ALTSVC_ALPNLEN] = "";
struct altsvc *as; struct altsvc *as;
unsigned short dstport = srcport; /* the same by default */ 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)); CURLcode result = getalnum(&p, alpnbuf, sizeof(alpnbuf));
if(result) size_t entries = 0;
return result; #ifdef CURL_DISABLE_VERBOSE_STRINGS
(void)data;
DEBUGASSERT(asi); #endif
if(result) {
/* Flush all cached alternatives for this source origin, if any */ infof(data, "Excessive alt-svc header, ignoring.");
altsvc_flush(asi, srcalpnid, srchost, srcport);
/* "clear" is a magic keyword */
if(strcasecompare(alpnbuf, "clear")) {
return CURLE_OK; return CURLE_OK;
} }
/* The 'ma' and 'persist' flags are annoyingly meant for all alternatives DEBUGASSERT(asi);
but are set after the list on the line. Scan for the semicolons and get
those fields first! */ /* "clear" is a magic keyword */
semip = p; if(strcasecompare(alpnbuf, "clear")) {
do { /* Flush cached alternatives for this source origin */
semip = strchr(semip, ';'); altsvc_flush(asi, srcalpnid, srchost, srcport);
if(semip) { return CURLE_OK;
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 { do {
if(*p == '=') { if(*p == '=') {
/* [protocol]="[host][:port]" */ /* [protocol]="[host][:port]" */
dstalpnid = alpn2alpnid(alpnbuf); enum alpnid dstalpnid = alpn2alpnid(alpnbuf); /* the same by default */
if(!dstalpnid) {
infof(data, "Unknown alt-svc protocol \"%s\", ignoring...\n", alpnbuf);
return CURLE_OK;
}
p++; p++;
if(*p == '\"') { if(*p == '\"') {
const char *dsthost; 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;
bool valid = TRUE;
p++; p++;
if(*p != ':') { if(*p != ':') {
/* host name starts here */ /* host name starts here */
@ -475,43 +502,109 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
while(*p && (ISALNUM(*p) || (*p == '.') || (*p == '-'))) while(*p && (ISALNUM(*p) || (*p == '.') || (*p == '-')))
p++; p++;
len = p - hostp; len = p - hostp;
if(!len || (len >= MAX_ALTSVC_HOSTLEN)) if(!len || (len >= MAX_ALTSVC_HOSTLEN)) {
return CURLE_BAD_FUNCTION_ARGUMENT; infof(data, "Excessive alt-svc host name, ignoring.");
memcpy(namebuf, hostp, len); valid = FALSE;
namebuf[len] = 0; }
dsthost = namebuf; else {
memcpy(namebuf, hostp, len);
namebuf[len] = 0;
dsthost = namebuf;
}
} }
else { else {
/* no destination name, use source host */ /* no destination name, use source host */
dsthost = srchost; dsthost = srchost;
} }
if(*p == ':') { if(*p == ':') {
/* a port number */ unsigned long port = 0;
char *end_ptr; p++;
unsigned long port = strtoul(++p, &end_ptr, 10); if(ISDIGIT(*p))
if(port > USHRT_MAX || end_ptr == p || *end_ptr != '\"') { /* a port number */
infof(data, "Unknown alt-svc port number, ignoring...\n"); port = strtoul(p, &end_ptr, 10);
return CURLE_OK; else
end_ptr = (char *)p; /* not left uninitialized */
if(!port || port > USHRT_MAX || end_ptr == p || *end_ptr != '\"') {
infof(data, "Unknown alt-svc port number, ignoring.");
valid = FALSE;
}
else {
dstport = curlx_ultous(port);
p = end_ptr;
} }
p = end_ptr;
dstport = curlx_ultous(port);
} }
if(*p++ != '\"') if(*p++ != '\"')
return CURLE_BAD_FUNCTION_ARGUMENT; break;
as = altsvc_createid(srchost, dsthost, /* Handle the optional 'ma' and 'persist' flags. Unknown flags
srcalpnid, dstalpnid, are skipped. */
srcport, dstport); for(;;) {
if(as) { while(ISBLANK(*p))
/* The expires time also needs to take the Age: value (if any) into p++;
account. [See RFC 7838 section 3.1] */ if(*p != ';')
as->expires = maxage + time(NULL); break;
as->persist = persist; p++; /* pass the semicolon */
Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node); if(!*p || ISNEWLINE(*p))
asi->num++; /* one more entry */ break;
infof(data, "Added alt-svc: %s:%d over %s\n", dsthost, dstport, result = getalnum(&p, option, sizeof(option));
Curl_alpnid2str(dstalpnid)); 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 && valid) {
if(!entries++)
/* Flush cached alternatives for this source origin, if any - when
this is the first entry of the line. */
altsvc_flush(asi, srcalpnid, srchost, srcport);
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);
infof(data, "Added alt-svc: %s:%d over %s", dsthost, dstport,
Curl_alpnid2str(dstalpnid));
}
} }
} }
else
break;
/* after the double quote there can be a comma if there's another /* after the double quote there can be a comma if there's another
string or a semicolon if no more */ string or a semicolon if no more */
if(*p == ',') { if(*p == ',') {
@ -519,11 +612,11 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
p++; p++;
result = getalnum(&p, alpnbuf, sizeof(alpnbuf)); result = getalnum(&p, alpnbuf, sizeof(alpnbuf));
if(result) if(result)
/* failed to parse, but since we already did at least one host we break;
return OK */
return CURLE_OK;
} }
} }
else
break;
} while(*p && (*p != ';') && (*p != '\n') && (*p != '\r')); } while(*p && (*p != ';') && (*p != '\n') && (*p != '\r'));
return CURLE_OK; return CURLE_OK;
@ -535,35 +628,35 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
bool Curl_altsvc_lookup(struct altsvcinfo *asi, bool Curl_altsvc_lookup(struct altsvcinfo *asi,
enum alpnid srcalpnid, const char *srchost, enum alpnid srcalpnid, const char *srchost,
int srcport, int srcport,
enum alpnid *dstalpnid, const char **dsthost, struct altsvc **dstentry,
int *dstport) const int versions) /* one or more bits */
{ {
struct curl_llist_element *e; struct Curl_llist_element *e;
struct curl_llist_element *n; struct Curl_llist_element *n;
time_t now = time(NULL); time_t now = time(NULL);
DEBUGASSERT(asi); DEBUGASSERT(asi);
DEBUGASSERT(srchost); DEBUGASSERT(srchost);
DEBUGASSERT(dsthost); DEBUGASSERT(dstentry);
for(e = asi->list.head; e; e = n) { for(e = asi->list.head; e; e = n) {
struct altsvc *as = e->ptr; struct altsvc *as = e->ptr;
n = e->next; n = e->next;
if(as->expires < now) { if(as->expires < now) {
/* an expired entry, remove */ /* an expired entry, remove */
Curl_llist_remove(&asi->list, e, NULL);
altsvc_free(as); altsvc_free(as);
continue; continue;
} }
if((as->srcalpnid == srcalpnid) && if((as->src.alpnid == srcalpnid) &&
strcasecompare(as->srchost, srchost) && hostcompare(srchost, as->src.host) &&
as->srcport == srcport) { (as->src.port == srcport) &&
(versions & as->dst.alpnid)) {
/* match */ /* match */
*dstalpnid = as->dstalpnid; *dstentry = as;
*dsthost = as->dsthost;
*dstport = as->dstport;
return TRUE; return TRUE;
} }
} }
return FALSE; return FALSE;
} }
#endif /* CURL_DISABLE_HTTP || USE_ALTSVC */ #endif /* !CURL_DISABLE_HTTP && !CURL_DISABLE_ALTSVC */

View file

@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -20,47 +20,50 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#include "curl_setup.h" #include "curl_setup.h"
#if !defined(CURL_DISABLE_HTTP) && defined(USE_ALTSVC) #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_ALTSVC)
#include <curl/curl.h> #include <curl/curl.h>
#include "llist.h" #include "llist.h"
enum alpnid { enum alpnid {
ALPN_none, ALPN_none = 0,
ALPN_h1, ALPN_h1 = CURLALTSVC_H1,
ALPN_h2, ALPN_h2 = CURLALTSVC_H2,
ALPN_h2c, ALPN_h3 = CURLALTSVC_H3
ALPN_h3 };
struct althost {
char *host;
unsigned short port;
enum alpnid alpnid;
}; };
struct altsvc { struct altsvc {
char *srchost; struct althost src;
char *dsthost; struct althost dst;
unsigned short srcport;
unsigned short dstport;
enum alpnid srcalpnid;
enum alpnid dstalpnid;
time_t expires; time_t expires;
bool persist; bool persist;
int prio; int prio;
struct curl_llist_element node; struct Curl_llist_element node;
}; };
struct altsvcinfo { struct altsvcinfo {
char *filename; char *filename;
struct curl_llist list; /* list of entries */ struct Curl_llist list; /* list of entries */
size_t num; /* number of alt-svc entries */
long flags; /* the publicly set bitmask */ long flags; /* the publicly set bitmask */
}; };
const char *Curl_alpnid2str(enum alpnid id); const char *Curl_alpnid2str(enum alpnid id);
struct altsvcinfo *Curl_altsvc_init(void); struct altsvcinfo *Curl_altsvc_init(void);
CURLcode Curl_altsvc_load(struct altsvcinfo *asi, const char *file); 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); CURLcode Curl_altsvc_ctrl(struct altsvcinfo *asi, const long ctrl);
void Curl_altsvc_cleanup(struct altsvcinfo *altsvc); void Curl_altsvc_cleanup(struct altsvcinfo **altsvc);
CURLcode Curl_altsvc_parse(struct Curl_easy *data, CURLcode Curl_altsvc_parse(struct Curl_easy *data,
struct altsvcinfo *altsvc, const char *value, struct altsvcinfo *altsvc, const char *value,
enum alpnid srcalpn, const char *srchost, enum alpnid srcalpn, const char *srchost,
@ -68,10 +71,11 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
bool Curl_altsvc_lookup(struct altsvcinfo *asi, bool Curl_altsvc_lookup(struct altsvcinfo *asi,
enum alpnid srcalpnid, const char *srchost, enum alpnid srcalpnid, const char *srchost,
int srcport, int srcport,
enum alpnid *dstalpnid, const char **dsthost, struct altsvc **dstentry,
int *dstport); const int versions); /* CURLALTSVC_H* bits */
#else #else
/* disabled */ /* disabled */
#define Curl_altsvc_save(a,b) #define Curl_altsvc_save(a,b,c)
#endif /* CURL_DISABLE_HTTP || USE_ALTSVC */ #define Curl_altsvc_cleanup(x)
#endif /* !CURL_DISABLE_HTTP && !CURL_DISABLE_ALTSVC */
#endif /* HEADER_CURL_ALTSVC_H */ #endif /* HEADER_CURL_ALTSVC_H */

View file

@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -18,13 +18,23 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#include "curl_setup.h" #include "curl_setup.h"
#ifdef __AMIGA__ #ifdef __AMIGA__
# include "amigaos.h"
# if defined(HAVE_PROTO_BSDSOCKET_H) && !defined(USE_AMISSL) #include <curl/curl.h>
#include "hostip.h"
#include "amigaos.h"
#ifdef HAVE_PROTO_BSDSOCKET_H
# if defined(__amigaos4__)
# include <bsdsocket/socketbasetags.h>
# elif !defined(USE_AMISSL)
# include <amitcp/socketbasetags.h> # include <amitcp/socketbasetags.h>
# endif # endif
# ifdef __libnix__ # ifdef __libnix__
@ -36,8 +46,154 @@
#include "curl_memory.h" #include "curl_memory.h"
#include "memdebug.h" #include "memdebug.h"
#ifdef __AMIGA__ #ifdef HAVE_PROTO_BSDSOCKET_H
#if defined(HAVE_PROTO_BSDSOCKET_H) && !defined(USE_AMISSL)
#ifdef __amigaos4__
/*
* AmigaOS 4.x specific code
*/
/*
* hostip4.c - Curl_ipv4_resolve_r() replacement code
*
* Logic that needs to be considered are the following build cases:
* - newlib networking
* - clib2 networking
* - direct bsdsocket.library networking (usually AmiSSL builds)
* Each with the threaded resolver enabled or not.
*
* With the threaded resolver enabled, try to use gethostbyname_r() where
* available, otherwise (re)open bsdsocket.library and fallback to
* gethostbyname().
*/
#include <proto/bsdsocket.h>
static struct SocketIFace *__CurlISocket = NULL;
static uint32 SocketFeatures = 0;
#define HAVE_BSDSOCKET_GETHOSTBYNAME_R 0x01
#define HAVE_BSDSOCKET_GETADDRINFO 0x02
CURLcode Curl_amiga_init(void)
{
struct SocketIFace *ISocket;
struct Library *base = OpenLibrary("bsdsocket.library", 4);
if(base) {
ISocket = (struct SocketIFace *)GetInterface(base, "main", 1, NULL);
if(ISocket) {
ULONG enabled = 0;
SocketBaseTags(SBTM_SETVAL(SBTC_CAN_SHARE_LIBRARY_BASES), TRUE,
SBTM_GETREF(SBTC_HAVE_GETHOSTADDR_R_API), (ULONG)&enabled,
TAG_DONE);
if(enabled) {
SocketFeatures |= HAVE_BSDSOCKET_GETHOSTBYNAME_R;
}
__CurlISocket = ISocket;
atexit(Curl_amiga_cleanup);
return CURLE_OK;
}
CloseLibrary(base);
}
return CURLE_FAILED_INIT;
}
void Curl_amiga_cleanup(void)
{
if(__CurlISocket) {
struct Library *base = __CurlISocket->Data.LibBase;
DropInterface((struct Interface *)__CurlISocket);
CloseLibrary(base);
__CurlISocket = NULL;
}
}
#ifdef CURLRES_AMIGA
/*
* Because we need to handle the different cases in hostip4.c at run-time,
* not at compile-time, based on what was detected in Curl_amiga_init(),
* we replace it completely with our own as to not complicate the baseline
* code. Assumes malloc/calloc/free are thread safe because Curl_he2ai()
* allocates memory also.
*/
struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
int port)
{
struct Curl_addrinfo *ai = NULL;
struct hostent *h;
struct SocketIFace *ISocket = __CurlISocket;
if(SocketFeatures & HAVE_BSDSOCKET_GETHOSTBYNAME_R) {
LONG h_errnop = 0;
struct hostent *buf;
buf = calloc(1, CURL_HOSTENT_SIZE);
if(buf) {
h = gethostbyname_r((STRPTR)hostname, buf,
(char *)buf + sizeof(struct hostent),
CURL_HOSTENT_SIZE - sizeof(struct hostent),
&h_errnop);
if(h) {
ai = Curl_he2ai(h, port);
}
free(buf);
}
}
else {
#ifdef CURLRES_THREADED
/* gethostbyname() is not thread safe, so we need to reopen bsdsocket
* on the thread's context
*/
struct Library *base = OpenLibrary("bsdsocket.library", 4);
if(base) {
ISocket = (struct SocketIFace *)GetInterface(base, "main", 1, NULL);
if(ISocket) {
h = gethostbyname((STRPTR)hostname);
if(h) {
ai = Curl_he2ai(h, port);
}
DropInterface((struct Interface *)ISocket);
}
CloseLibrary(base);
}
#else
/* not using threaded resolver - safe to use this as-is */
h = gethostbyname(hostname);
if(h) {
ai = Curl_he2ai(h, port);
}
#endif
}
return ai;
}
#endif /* CURLRES_AMIGA */
#ifdef USE_AMISSL
int Curl_amiga_select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *errorfds, struct timeval *timeout)
{
int r = WaitSelect(nfds, readfds, writefds, errorfds, timeout, 0);
/* Ensure Ctrl-C signal is actioned */
if((r == -1) && (SOCKERRNO == EINTR))
raise(SIGINT);
return r;
}
#endif /* USE_AMISSL */
#elif !defined(USE_AMISSL) /* __amigaos4__ */
/*
* Amiga OS3 specific code
*/
struct Library *SocketBase = NULL; struct Library *SocketBase = NULL;
extern int errno, h_errno; extern int errno, h_errno;
@ -47,7 +203,7 @@ void __request(const char *msg);
# define __request(msg) Printf(msg "\n\a") # define __request(msg) Printf(msg "\n\a")
#endif #endif
void Curl_amiga_cleanup() void Curl_amiga_cleanup(void)
{ {
if(SocketBase) { if(SocketBase) {
CloseLibrary(SocketBase); CloseLibrary(SocketBase);
@ -55,41 +211,36 @@ void Curl_amiga_cleanup()
} }
} }
bool Curl_amiga_init() CURLcode Curl_amiga_init(void)
{ {
if(!SocketBase) if(!SocketBase)
SocketBase = OpenLibrary("bsdsocket.library", 4); SocketBase = OpenLibrary("bsdsocket.library", 4);
if(!SocketBase) { if(!SocketBase) {
__request("No TCP/IP Stack running!"); __request("No TCP/IP Stack running!");
return FALSE; return CURLE_FAILED_INIT;
} }
if(SocketBaseTags(SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))), (ULONG) &errno, if(SocketBaseTags(SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))), (ULONG) &errno,
SBTM_SETVAL(SBTC_LOGTAGPTR), (ULONG) "curl", SBTM_SETVAL(SBTC_LOGTAGPTR), (ULONG) "curl",
TAG_DONE)) { TAG_DONE)) {
__request("SocketBaseTags ERROR"); __request("SocketBaseTags ERROR");
return FALSE; return CURLE_FAILED_INIT;
} }
#ifndef __libnix__ #ifndef __libnix__
atexit(Curl_amiga_cleanup); atexit(Curl_amiga_cleanup);
#endif #endif
return TRUE; return CURLE_OK;
} }
#ifdef __libnix__ #ifdef __libnix__
ADD2EXIT(Curl_amiga_cleanup, -50); ADD2EXIT(Curl_amiga_cleanup, -50);
#endif #endif
#endif /* !USE_AMISSL */
#endif /* HAVE_PROTO_BSDSOCKET_H */ #endif /* HAVE_PROTO_BSDSOCKET_H */
#ifdef USE_AMISSL
void Curl_amiga_X509_free(X509 *a)
{
X509_free(a);
}
#endif /* USE_AMISSL */
#endif /* __AMIGA__ */ #endif /* __AMIGA__ */

View file

@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -20,25 +20,23 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#include "curl_setup.h" #include "curl_setup.h"
#if defined(__AMIGA__) && defined(HAVE_BSDSOCKET_H) && !defined(USE_AMISSL) #if defined(__AMIGA__) && defined(HAVE_PROTO_BSDSOCKET_H) && \
(!defined(USE_AMISSL) || defined(__amigaos4__))
bool Curl_amiga_init(); CURLcode Curl_amiga_init(void);
void Curl_amiga_cleanup(); void Curl_amiga_cleanup(void);
#else #else
#define Curl_amiga_init() 1 #define Curl_amiga_init() CURLE_OK
#define Curl_amiga_cleanup() Curl_nop_stmt #define Curl_amiga_cleanup() Curl_nop_stmt
#endif #endif
#ifdef USE_AMISSL
#include <openssl/x509v3.h>
void Curl_amiga_X509_free(X509 *a);
#endif /* USE_AMISSL */
#endif /* HEADER_CURL_AMIGAOS_H */ #endif /* HEADER_CURL_AMIGAOS_H */

View file

@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#ifndef CURL_DISABLE_TELNET #ifndef CURL_DISABLE_TELNET
/* /*

View file

@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#include "curl_setup.h" #include "curl_setup.h"
@ -45,30 +47,21 @@
#include <inet.h> #include <inet.h>
#endif #endif
#ifdef HAVE_PROCESS_H
#include <process.h>
#endif
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
#undef in_addr_t
#define in_addr_t unsigned long
#endif
#include "urldata.h" #include "urldata.h"
#include "sendf.h" #include "sendf.h"
#include "hostip.h" #include "hostip.h"
#include "hash.h" #include "hash.h"
#include "share.h" #include "share.h"
#include "strerror.h"
#include "url.h" #include "url.h"
#include "multiif.h" #include "multiif.h"
#include "inet_pton.h" #include "inet_pton.h"
#include "connect.h" #include "connect.h"
#include "select.h" #include "select.h"
#include "progress.h" #include "progress.h"
#include "timediff.h"
# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \ # if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
(defined(WIN32) || defined(__SYMBIAN32__)) defined(WIN32)
# define CARES_STATICLIB # define CARES_STATICLIB
# endif # endif
# include <ares.h> # include <ares.h>
@ -80,16 +73,40 @@
#define HAVE_CARES_CALLBACK_TIMEOUTS 1 #define HAVE_CARES_CALLBACK_TIMEOUTS 1
#endif #endif
#if ARES_VERSION >= 0x010601
/* IPv6 supported since 1.6.1 */
#define HAVE_CARES_IPV6 1
#endif
#if ARES_VERSION >= 0x010704
#define HAVE_CARES_SERVERS_CSV 1
#define HAVE_CARES_LOCAL_DEV 1
#define HAVE_CARES_SET_LOCAL 1
#endif
#if ARES_VERSION >= 0x010b00
#define HAVE_CARES_PORTS_CSV 1
#endif
#if ARES_VERSION >= 0x011000
/* 1.16.0 or later has ares_getaddrinfo */
#define HAVE_CARES_GETADDRINFO 1
#endif
/* The last 3 #include files should be in this order */ /* The last 3 #include files should be in this order */
#include "curl_printf.h" #include "curl_printf.h"
#include "curl_memory.h" #include "curl_memory.h"
#include "memdebug.h" #include "memdebug.h"
struct ResolverResults { struct thread_data {
int num_pending; /* number of ares_gethostbyname() requests */ int num_pending; /* number of outstanding c-ares requests */
Curl_addrinfo *temp_ai; /* intermediary result while fetching c-ares parts */ struct Curl_addrinfo *temp_ai; /* intermediary result while fetching c-ares
parts */
int last_status; int last_status;
#ifndef HAVE_CARES_GETADDRINFO
struct curltime happy_eyeballs_dns_time; /* when this timer started, or 0 */ struct curltime happy_eyeballs_dns_time; /* when this timer started, or 0 */
#endif
char hostname[1];
}; };
/* How long we are willing to wait for additional parallel responses after /* How long we are willing to wait for additional parallel responses after
@ -132,8 +149,8 @@ void Curl_resolver_global_cleanup(void)
} }
static void Curl_ares_sock_state_cb(void *data, ares_socket_t socket_fd, static void sock_state_cb(void *data, ares_socket_t socket_fd,
int readable, int writable) int readable, int writable)
{ {
struct Curl_easy *easy = data; struct Curl_easy *easy = data;
if(!readable && !writable) { if(!readable && !writable) {
@ -154,7 +171,7 @@ CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver)
int status; int status;
struct ares_options options; struct ares_options options;
int optmask = ARES_OPT_SOCK_STATE_CB; int optmask = ARES_OPT_SOCK_STATE_CB;
options.sock_state_cb = Curl_ares_sock_state_cb; options.sock_state_cb = sock_state_cb;
options.sock_state_cb_data = easy; options.sock_state_cb_data = easy;
status = ares_init_options((ares_channel*)resolver, &options, optmask); status = ares_init_options((ares_channel*)resolver, &options, optmask);
if(status != ARES_SUCCESS) { if(status != ARES_SUCCESS) {
@ -203,22 +220,23 @@ static void destroy_async_data(struct Curl_async *async);
/* /*
* Cancel all possibly still on-going resolves for this connection. * Cancel all possibly still on-going resolves for this connection.
*/ */
void Curl_resolver_cancel(struct connectdata *conn) void Curl_resolver_cancel(struct Curl_easy *data)
{ {
if(conn->data && conn->data->state.resolver) DEBUGASSERT(data);
ares_cancel((ares_channel)conn->data->state.resolver); if(data->state.async.resolver)
destroy_async_data(&conn->async); ares_cancel((ares_channel)data->state.async.resolver);
destroy_async_data(&data->state.async);
} }
/* /*
* We're equivalent to Curl_resolver_cancel() for the c-ares resolver. We * We're equivalent to Curl_resolver_cancel() for the c-ares resolver. We
* never block. * never block.
*/ */
void Curl_resolver_kill(struct connectdata *conn) void Curl_resolver_kill(struct Curl_easy *data)
{ {
/* We don't need to check the resolver state because we can be called safely /* We don't need to check the resolver state because we can be called safely
at any time and we always do the same thing. */ at any time and we always do the same thing. */
Curl_resolver_cancel(conn); Curl_resolver_cancel(data);
} }
/* /*
@ -226,10 +244,8 @@ void Curl_resolver_kill(struct connectdata *conn)
*/ */
static void destroy_async_data(struct Curl_async *async) static void destroy_async_data(struct Curl_async *async)
{ {
free(async->hostname); if(async->tdata) {
struct thread_data *res = async->tdata;
if(async->os_specific) {
struct ResolverResults *res = (struct ResolverResults *)async->os_specific;
if(res) { if(res) {
if(res->temp_ai) { if(res->temp_ai) {
Curl_freeaddrinfo(res->temp_ai); Curl_freeaddrinfo(res->temp_ai);
@ -237,10 +253,8 @@ static void destroy_async_data(struct Curl_async *async)
} }
free(res); free(res);
} }
async->os_specific = NULL; async->tdata = NULL;
} }
async->hostname = NULL;
} }
/* /*
@ -252,27 +266,25 @@ static void destroy_async_data(struct Curl_async *async)
* Returns: sockets-in-use-bitmap * Returns: sockets-in-use-bitmap
*/ */
int Curl_resolver_getsock(struct connectdata *conn, int Curl_resolver_getsock(struct Curl_easy *data,
curl_socket_t *socks, curl_socket_t *socks)
int numsocks)
{ {
struct timeval maxtime; struct timeval maxtime;
struct timeval timebuf; struct timeval timebuf;
struct timeval *timeout; struct timeval *timeout;
long milli; long milli;
int max = ares_getsock((ares_channel)conn->data->state.resolver, int max = ares_getsock((ares_channel)data->state.async.resolver,
(ares_socket_t *)socks, numsocks); (ares_socket_t *)socks, MAX_SOCKSPEREASYHANDLE);
maxtime.tv_sec = CURL_TIMEOUT_RESOLVE; maxtime.tv_sec = CURL_TIMEOUT_RESOLVE;
maxtime.tv_usec = 0; maxtime.tv_usec = 0;
timeout = ares_timeout((ares_channel)conn->data->state.resolver, &maxtime, timeout = ares_timeout((ares_channel)data->state.async.resolver, &maxtime,
&timebuf); &timebuf);
milli = (timeout->tv_sec * 1000) + (timeout->tv_usec/1000); milli = (long)curlx_tvtoms(timeout);
if(milli == 0) if(milli == 0)
milli += 10; milli += 10;
Curl_expire(conn->data, milli, EXPIRE_ASYNC_NAME); Curl_expire(data, milli, EXPIRE_ASYNC_NAME);
return max; return max;
} }
@ -284,12 +296,11 @@ int Curl_resolver_getsock(struct connectdata *conn,
* 2) wait for the timeout period to check for action on ares' sockets. * 2) wait for the timeout period to check for action on ares' sockets.
* 3) tell ares to act on all the sockets marked as "with action" * 3) tell ares to act on all the sockets marked as "with action"
* *
* return number of sockets it worked on * return number of sockets it worked on, or -1 on error
*/ */
static int waitperform(struct connectdata *conn, int timeout_ms) static int waitperform(struct Curl_easy *data, timediff_t timeout_ms)
{ {
struct Curl_easy *data = conn->data;
int nfds; int nfds;
int bitmask; int bitmask;
ares_socket_t socks[ARES_GETSOCK_MAXNUM]; ares_socket_t socks[ARES_GETSOCK_MAXNUM];
@ -297,7 +308,7 @@ static int waitperform(struct connectdata *conn, int timeout_ms)
int i; int i;
int num = 0; int num = 0;
bitmask = ares_getsock((ares_channel)data->state.resolver, socks, bitmask = ares_getsock((ares_channel)data->state.async.resolver, socks,
ARES_GETSOCK_MAXNUM); ARES_GETSOCK_MAXNUM);
for(i = 0; i < ARES_GETSOCK_MAXNUM; i++) { for(i = 0; i < ARES_GETSOCK_MAXNUM; i++) {
@ -311,26 +322,29 @@ static int waitperform(struct connectdata *conn, int timeout_ms)
pfd[i].fd = socks[i]; pfd[i].fd = socks[i];
pfd[i].events |= POLLWRNORM|POLLOUT; pfd[i].events |= POLLWRNORM|POLLOUT;
} }
if(pfd[i].events != 0) if(pfd[i].events)
num++; num++;
else else
break; break;
} }
if(num) if(num) {
nfds = Curl_poll(pfd, num, timeout_ms); nfds = Curl_poll(pfd, num, timeout_ms);
if(nfds < 0)
return -1;
}
else else
nfds = 0; nfds = 0;
if(!nfds) if(!nfds)
/* Call ares_process() unconditonally here, even if we simply timed out /* Call ares_process() unconditionally here, even if we simply timed out
above, as otherwise the ares name resolve won't timeout! */ above, as otherwise the ares name resolve won't timeout! */
ares_process_fd((ares_channel)data->state.resolver, ARES_SOCKET_BAD, ares_process_fd((ares_channel)data->state.async.resolver, ARES_SOCKET_BAD,
ARES_SOCKET_BAD); ARES_SOCKET_BAD);
else { else {
/* move through the descriptors and ask for processing on them */ /* move through the descriptors and ask for processing on them */
for(i = 0; i < num; i++) for(i = 0; i < num; i++)
ares_process_fd((ares_channel)data->state.resolver, ares_process_fd((ares_channel)data->state.async.resolver,
(pfd[i].revents & (POLLRDNORM|POLLIN))? (pfd[i].revents & (POLLRDNORM|POLLIN))?
pfd[i].fd:ARES_SOCKET_BAD, pfd[i].fd:ARES_SOCKET_BAD,
(pfd[i].revents & (POLLWRNORM|POLLOUT))? (pfd[i].revents & (POLLWRNORM|POLLOUT))?
@ -346,19 +360,19 @@ static int waitperform(struct connectdata *conn, int timeout_ms)
* *
* Returns normal CURLcode errors. * Returns normal CURLcode errors.
*/ */
CURLcode Curl_resolver_is_resolved(struct connectdata *conn, CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
struct Curl_dns_entry **dns) struct Curl_dns_entry **dns)
{ {
struct Curl_easy *data = conn->data; struct thread_data *res = data->state.async.tdata;
struct ResolverResults *res = (struct ResolverResults *)
conn->async.os_specific;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
if(dns) DEBUGASSERT(dns);
*dns = NULL; *dns = NULL;
waitperform(conn, 0); if(waitperform(data, 0) < 0)
return CURLE_UNRECOVERABLE_POLL;
#ifndef HAVE_CARES_GETADDRINFO
/* Now that we've checked for any last minute results above, see if there are /* Now that we've checked for any last minute results above, see if there are
any responses still pending when the EXPIRE_HAPPY_EYEBALLS_DNS timer any responses still pending when the EXPIRE_HAPPY_EYEBALLS_DNS timer
expires. */ expires. */
@ -378,27 +392,23 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
ARES_ECANCELLED synchronously for all pending responses. This will ARES_ECANCELLED synchronously for all pending responses. This will
leave us with res->num_pending == 0, which is perfect for the next leave us with res->num_pending == 0, which is perfect for the next
block. */ block. */
ares_cancel((ares_channel)data->state.resolver); ares_cancel((ares_channel)data->state.async.resolver);
DEBUGASSERT(res->num_pending == 0); DEBUGASSERT(res->num_pending == 0);
} }
#endif
if(res && !res->num_pending) { if(res && !res->num_pending) {
if(dns) { (void)Curl_addrinfo_callback(data, res->last_status, res->temp_ai);
(void)Curl_addrinfo_callback(conn, res->last_status, res->temp_ai); /* temp_ai ownership is moved to the connection, so we need not free-up
/* temp_ai ownership is moved to the connection, so we need not free-up them */
them */ res->temp_ai = NULL;
res->temp_ai = NULL;
}
if(!conn->async.dns) {
failf(data, "Could not resolve: %s (%s)",
conn->async.hostname, ares_strerror(conn->async.status));
result = conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
CURLE_COULDNT_RESOLVE_HOST;
}
else if(dns)
*dns = conn->async.dns;
destroy_async_data(&conn->async); if(!data->state.async.dns)
result = Curl_resolver_error(data);
else
*dns = data->state.async.dns;
destroy_async_data(&data->state.async);
} }
return result; return result;
@ -410,27 +420,25 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
* Waits for a resolve to finish. This function should be avoided since using * Waits for a resolve to finish. This function should be avoided since using
* this risk getting the multi interface to "hang". * this risk getting the multi interface to "hang".
* *
* If 'entry' is non-NULL, make it point to the resolved dns entry * 'entry' MUST be non-NULL.
* *
* Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved,
* CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors. * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
*/ */
CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
struct Curl_dns_entry **entry) struct Curl_dns_entry **entry)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
timediff_t timeout; timediff_t timeout;
struct curltime now = Curl_now(); struct curltime now = Curl_now();
struct Curl_dns_entry *temp_entry;
if(entry) DEBUGASSERT(entry);
*entry = NULL; /* clear on entry */ *entry = NULL; /* clear on entry */
timeout = Curl_timeleft(data, &now, TRUE); timeout = Curl_timeleft(data, &now, TRUE);
if(timeout < 0) { if(timeout < 0) {
/* already expired! */ /* already expired! */
connclose(conn, "Timed out before name resolve started"); connclose(data->conn, "Timed out before name resolve started");
return CURLE_OPERATION_TIMEDOUT; return CURLE_OPERATION_TIMEDOUT;
} }
if(!timeout) if(!timeout)
@ -440,30 +448,35 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
while(!result) { while(!result) {
struct timeval *tvp, tv, store; struct timeval *tvp, tv, store;
int itimeout; int itimeout;
int timeout_ms; timediff_t timeout_ms;
itimeout = (timeout > (long)INT_MAX) ? INT_MAX : (int)timeout; #if TIMEDIFF_T_MAX > INT_MAX
itimeout = (timeout > INT_MAX) ? INT_MAX : (int)timeout;
#else
itimeout = (int)timeout;
#endif
store.tv_sec = itimeout/1000; store.tv_sec = itimeout/1000;
store.tv_usec = (itimeout%1000)*1000; store.tv_usec = (itimeout%1000)*1000;
tvp = ares_timeout((ares_channel)data->state.resolver, &store, &tv); tvp = ares_timeout((ares_channel)data->state.async.resolver, &store, &tv);
/* use the timeout period ares returned to us above if less than one /* use the timeout period ares returned to us above if less than one
second is left, otherwise just use 1000ms to make sure the progress second is left, otherwise just use 1000ms to make sure the progress
callback gets called frequent enough */ callback gets called frequent enough */
if(!tvp->tv_sec) if(!tvp->tv_sec)
timeout_ms = (int)(tvp->tv_usec/1000); timeout_ms = (timediff_t)(tvp->tv_usec/1000);
else else
timeout_ms = 1000; timeout_ms = 1000;
waitperform(conn, timeout_ms); if(waitperform(data, timeout_ms) < 0)
result = Curl_resolver_is_resolved(conn, entry?&temp_entry:NULL); return CURLE_UNRECOVERABLE_POLL;
result = Curl_resolver_is_resolved(data, entry);
if(result || conn->async.done) if(result || data->state.async.done)
break; break;
if(Curl_pgrsUpdate(conn)) if(Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK; result = CURLE_ABORTED_BY_CALLBACK;
else { else {
struct curltime now2 = Curl_now(); struct curltime now2 = Curl_now();
@ -473,7 +486,7 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
else if(timediff > timeout) else if(timediff > timeout)
timeout = -1; timeout = -1;
else else
timeout -= (long)timediff; timeout -= timediff;
now = now2; /* for next loop */ now = now2; /* for next loop */
} }
if(timeout < 0) if(timeout < 0)
@ -481,36 +494,52 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
} }
if(result) if(result)
/* failure, so we cancel the ares operation */ /* failure, so we cancel the ares operation */
ares_cancel((ares_channel)data->state.resolver); ares_cancel((ares_channel)data->state.async.resolver);
/* Operation complete, if the lookup was successful we now have the entry /* Operation complete, if the lookup was successful we now have the entry
in the cache. */ in the cache. */
if(entry) if(entry)
*entry = conn->async.dns; *entry = data->state.async.dns;
if(result) if(result)
/* close the connection, since we can't return failure here without /* close the connection, since we can't return failure here without
cleaning up this connection properly. */ cleaning up this connection properly. */
connclose(conn, "c-ares resolve failed"); connclose(data->conn, "c-ares resolve failed");
return result; return result;
} }
#ifndef HAVE_CARES_GETADDRINFO
/* Connects results to the list */ /* Connects results to the list */
static void compound_results(struct ResolverResults *res, static void compound_results(struct thread_data *res,
Curl_addrinfo *ai) struct Curl_addrinfo *ai)
{ {
Curl_addrinfo *ai_tail;
if(!ai) if(!ai)
return; return;
ai_tail = ai;
while(ai_tail->ai_next) #ifdef ENABLE_IPV6 /* CURLRES_IPV6 */
ai_tail = ai_tail->ai_next; if(res->temp_ai && res->temp_ai->ai_family == PF_INET6) {
/* We have results already, put the new IPv6 entries at the head of the
list. */
struct Curl_addrinfo *temp_ai_tail = res->temp_ai;
/* Add the new results to the list of old results. */ while(temp_ai_tail->ai_next)
ai_tail->ai_next = res->temp_ai; temp_ai_tail = temp_ai_tail->ai_next;
res->temp_ai = ai;
temp_ai_tail->ai_next = ai;
}
else
#endif /* CURLRES_IPV6 */
{
/* Add the new results to the list of old results. */
struct Curl_addrinfo *ai_tail = ai;
while(ai_tail->ai_next)
ai_tail = ai_tail->ai_next;
ai_tail->ai_next = res->temp_ai;
res->temp_ai = ai;
}
} }
/* /*
@ -525,8 +554,8 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */
#endif #endif
struct hostent *hostent) struct hostent *hostent)
{ {
struct connectdata *conn = (struct connectdata *)arg; struct Curl_easy *data = (struct Curl_easy *)arg;
struct ResolverResults *res; struct thread_data *res;
#ifdef HAVE_CARES_CALLBACK_TIMEOUTS #ifdef HAVE_CARES_CALLBACK_TIMEOUTS
(void)timeouts; /* ignored */ (void)timeouts; /* ignored */
@ -537,12 +566,12 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */
be valid so only defer it when we know the 'status' says its fine! */ be valid so only defer it when we know the 'status' says its fine! */
return; return;
res = (struct ResolverResults *)conn->async.os_specific; res = data->state.async.tdata;
if(res) { if(res) {
res->num_pending--; res->num_pending--;
if(CURL_ASYNC_SUCCESS == status) { if(CURL_ASYNC_SUCCESS == status) {
Curl_addrinfo *ai = Curl_he2ai(hostent, conn->async.port); struct Curl_addrinfo *ai = Curl_he2ai(hostent, data->state.async.port);
if(ai) { if(ai) {
compound_results(res, ai); compound_results(res, ai);
} }
@ -607,112 +636,180 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */
c-ares retry cycle each request is. c-ares retry cycle each request is.
*/ */
res->happy_eyeballs_dns_time = Curl_now(); res->happy_eyeballs_dns_time = Curl_now();
Curl_expire( Curl_expire(data, HAPPY_EYEBALLS_DNS_TIMEOUT,
conn->data, HAPPY_EYEBALLS_DNS_TIMEOUT, EXPIRE_HAPPY_EYEBALLS_DNS); EXPIRE_HAPPY_EYEBALLS_DNS);
} }
} }
} }
#else
/* c-ares 1.16.0 or later */
/*
* ares2addr() converts an address list provided by c-ares to an internal
* libcurl compatible list
*/
static struct Curl_addrinfo *ares2addr(struct ares_addrinfo_node *node)
{
/* traverse the ares_addrinfo_node list */
struct ares_addrinfo_node *ai;
struct Curl_addrinfo *cafirst = NULL;
struct Curl_addrinfo *calast = NULL;
int error = 0;
for(ai = node; ai != NULL; ai = ai->ai_next) {
size_t ss_size;
struct Curl_addrinfo *ca;
/* ignore elements with unsupported address family, */
/* settle family-specific sockaddr structure size. */
if(ai->ai_family == AF_INET)
ss_size = sizeof(struct sockaddr_in);
#ifdef ENABLE_IPV6
else if(ai->ai_family == AF_INET6)
ss_size = sizeof(struct sockaddr_in6);
#endif
else
continue;
/* ignore elements without required address info */
if(!ai->ai_addr || !(ai->ai_addrlen > 0))
continue;
/* ignore elements with bogus address size */
if((size_t)ai->ai_addrlen < ss_size)
continue;
ca = malloc(sizeof(struct Curl_addrinfo) + ss_size);
if(!ca) {
error = EAI_MEMORY;
break;
}
/* copy each structure member individually, member ordering, */
/* size, or padding might be different for each platform. */
ca->ai_flags = ai->ai_flags;
ca->ai_family = ai->ai_family;
ca->ai_socktype = ai->ai_socktype;
ca->ai_protocol = ai->ai_protocol;
ca->ai_addrlen = (curl_socklen_t)ss_size;
ca->ai_addr = NULL;
ca->ai_canonname = NULL;
ca->ai_next = NULL;
ca->ai_addr = (void *)((char *)ca + sizeof(struct Curl_addrinfo));
memcpy(ca->ai_addr, ai->ai_addr, ss_size);
/* if the return list is empty, this becomes the first element */
if(!cafirst)
cafirst = ca;
/* add this element last in the return list */
if(calast)
calast->ai_next = ca;
calast = ca;
}
/* if we failed, destroy the Curl_addrinfo list */
if(error) {
Curl_freeaddrinfo(cafirst);
cafirst = NULL;
}
return cafirst;
}
static void addrinfo_cb(void *arg, int status, int timeouts,
struct ares_addrinfo *result)
{
struct Curl_easy *data = (struct Curl_easy *)arg;
struct thread_data *res = data->state.async.tdata;
(void)timeouts;
if(ARES_SUCCESS == status) {
res->temp_ai = ares2addr(result->nodes);
res->last_status = CURL_ASYNC_SUCCESS;
ares_freeaddrinfo(result);
}
res->num_pending--;
}
#endif
/* /*
* Curl_resolver_getaddrinfo() - when using ares * Curl_resolver_getaddrinfo() - when using ares
* *
* Returns name information about the given hostname and port number. If * Returns name information about the given hostname and port number. If
* successful, the 'hostent' is returned and the forth argument will point to * successful, the 'hostent' is returned and the fourth argument will point to
* memory we need to free after use. That memory *MUST* be freed with * memory we need to free after use. That memory *MUST* be freed with
* Curl_freeaddrinfo(), nothing else. * Curl_freeaddrinfo(), nothing else.
*/ */
Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
const char *hostname, const char *hostname,
int port, int port,
int *waitp) int *waitp)
{ {
char *bufp; struct thread_data *res = NULL;
struct Curl_easy *data = conn->data; size_t namelen = strlen(hostname);
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 */ *waitp = 0; /* default to synchronous response */
/* First check if this is an IPv4 address string */ res = calloc(sizeof(struct thread_data) + namelen, 1);
if(Curl_inet_pton(AF_INET, hostname, &in) > 0) { if(res) {
/* This is a dotted IP address 123.123.123.123-style */ strcpy(res->hostname, hostname);
return Curl_ip2addr(AF_INET, &in, hostname, port); data->state.async.hostname = res->hostname;
} data->state.async.port = port;
data->state.async.done = FALSE; /* not done */
#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */ data->state.async.status = 0; /* clear */
/* Otherwise, check if this is an IPv6 address string */ data->state.async.dns = NULL; /* clear */
if(Curl_inet_pton (AF_INET6, hostname, &in6) > 0) data->state.async.tdata = res;
/* This must be an IPv6 address literal. */
return Curl_ip2addr(AF_INET6, &in6, hostname, port);
switch(conn->ip_version) {
default:
#if ARES_VERSION >= 0x010601
family = PF_UNSPEC; /* supported by c-ares since 1.6.1, so for older
c-ares versions this just falls through and defaults
to PF_INET */
break;
#endif
case CURL_IPRESOLVE_V4:
family = PF_INET;
break;
case CURL_IPRESOLVE_V6:
family = PF_INET6;
break;
}
#endif /* CURLRES_IPV6 */
bufp = strdup(hostname);
if(bufp) {
struct ResolverResults *res = NULL;
free(conn->async.hostname);
conn->async.hostname = bufp;
conn->async.port = port;
conn->async.done = FALSE; /* not done */
conn->async.status = 0; /* clear */
conn->async.dns = NULL; /* clear */
res = calloc(sizeof(struct ResolverResults), 1);
if(!res) {
free(conn->async.hostname);
conn->async.hostname = NULL;
return NULL;
}
conn->async.os_specific = res;
/* initial status - failed */ /* initial status - failed */
res->last_status = ARES_ENOTFOUND; res->last_status = ARES_ENOTFOUND;
#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */
if(family == PF_UNSPEC) {
if(Curl_ipv6works()) {
res->num_pending = 2;
/* areschannel is already setup in the Curl_open() function */ #ifdef HAVE_CARES_GETADDRINFO
ares_gethostbyname((ares_channel)data->state.resolver, hostname, {
PF_INET, query_completed_cb, conn); struct ares_addrinfo_hints hints;
ares_gethostbyname((ares_channel)data->state.resolver, hostname, char service[12];
PF_INET6, query_completed_cb, conn); int pf = PF_INET;
} memset(&hints, 0, sizeof(hints));
else { #ifdef CURLRES_IPV6
res->num_pending = 1; if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data))
/* The stack seems to be IPv6-enabled */
pf = PF_UNSPEC;
#endif /* CURLRES_IPV6 */
hints.ai_family = pf;
hints.ai_socktype = (data->conn->transport == TRNSPRT_TCP)?
SOCK_STREAM : SOCK_DGRAM;
/* Since the service is a numerical one, set the hint flags
* accordingly to save a call to getservbyname in inside C-Ares
*/
hints.ai_flags = ARES_AI_NUMERICSERV;
msnprintf(service, sizeof(service), "%d", port);
res->num_pending = 1;
ares_getaddrinfo((ares_channel)data->state.async.resolver, hostname,
service, &hints, addrinfo_cb, data);
}
#else
/* areschannel is already setup in the Curl_open() function */ #ifdef HAVE_CARES_IPV6
ares_gethostbyname((ares_channel)data->state.resolver, hostname, if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data)) {
PF_INET, query_completed_cb, conn); /* The stack seems to be IPv6-enabled */
} res->num_pending = 2;
/* areschannel is already setup in the Curl_open() function */
ares_gethostbyname((ares_channel)data->state.async.resolver, hostname,
PF_INET, query_completed_cb, data);
ares_gethostbyname((ares_channel)data->state.async.resolver, hostname,
PF_INET6, query_completed_cb, data);
} }
else else
#endif /* CURLRES_IPV6 */ #endif
{ {
res->num_pending = 1; res->num_pending = 1;
/* areschannel is already setup in the Curl_open() function */ /* areschannel is already setup in the Curl_open() function */
ares_gethostbyname((ares_channel)data->state.resolver, hostname, family, ares_gethostbyname((ares_channel)data->state.async.resolver,
query_completed_cb, conn); hostname, PF_INET,
query_completed_cb, data);
} }
#endif
*waitp = 1; /* expect asynchronous response */ *waitp = 1; /* expect asynchronous response */
} }
return NULL; /* no struct yet */ return NULL; /* no struct yet */
@ -733,8 +830,13 @@ CURLcode Curl_set_dns_servers(struct Curl_easy *data,
if(!(servers && servers[0])) if(!(servers && servers[0]))
return CURLE_OK; return CURLE_OK;
#if (ARES_VERSION >= 0x010704) #ifdef HAVE_CARES_SERVERS_CSV
ares_result = ares_set_servers_csv(data->state.resolver, servers); #ifdef HAVE_CARES_PORTS_CSV
ares_result = ares_set_servers_ports_csv(data->state.async.resolver,
servers);
#else
ares_result = ares_set_servers_csv(data->state.async.resolver, servers);
#endif
switch(ares_result) { switch(ares_result) {
case ARES_SUCCESS: case ARES_SUCCESS:
result = CURLE_OK; result = CURLE_OK;
@ -759,11 +861,11 @@ CURLcode Curl_set_dns_servers(struct Curl_easy *data,
CURLcode Curl_set_dns_interface(struct Curl_easy *data, CURLcode Curl_set_dns_interface(struct Curl_easy *data,
const char *interf) const char *interf)
{ {
#if (ARES_VERSION >= 0x010704) #ifdef HAVE_CARES_LOCAL_DEV
if(!interf) if(!interf)
interf = ""; interf = "";
ares_set_local_dev((ares_channel)data->state.resolver, interf); ares_set_local_dev((ares_channel)data->state.async.resolver, interf);
return CURLE_OK; return CURLE_OK;
#else /* c-ares version too old! */ #else /* c-ares version too old! */
@ -776,7 +878,7 @@ CURLcode Curl_set_dns_interface(struct Curl_easy *data,
CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data, CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data,
const char *local_ip4) const char *local_ip4)
{ {
#if (ARES_VERSION >= 0x010704) #ifdef HAVE_CARES_SET_LOCAL
struct in_addr a4; struct in_addr a4;
if((!local_ip4) || (local_ip4[0] == 0)) { if((!local_ip4) || (local_ip4[0] == 0)) {
@ -788,7 +890,8 @@ CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data,
} }
} }
ares_set_local_ip4((ares_channel)data->state.resolver, ntohl(a4.s_addr)); ares_set_local_ip4((ares_channel)data->state.async.resolver,
ntohl(a4.s_addr));
return CURLE_OK; return CURLE_OK;
#else /* c-ares version too old! */ #else /* c-ares version too old! */
@ -801,7 +904,7 @@ CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data,
CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data, CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data,
const char *local_ip6) const char *local_ip6)
{ {
#if (ARES_VERSION >= 0x010704) && defined(ENABLE_IPV6) #if defined(HAVE_CARES_SET_LOCAL) && defined(ENABLE_IPV6)
unsigned char a6[INET6_ADDRSTRLEN]; unsigned char a6[INET6_ADDRSTRLEN];
if((!local_ip6) || (local_ip6[0] == 0)) { if((!local_ip6) || (local_ip6[0] == 0)) {
@ -814,7 +917,7 @@ CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data,
} }
} }
ares_set_local_ip6((ares_channel)data->state.resolver, a6); ares_set_local_ip6((ares_channel)data->state.async.resolver, a6);
return CURLE_OK; return CURLE_OK;
#else /* c-ares version too old! */ #else /* c-ares version too old! */

View file

@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -18,9 +18,12 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#include "curl_setup.h" #include "curl_setup.h"
#include "socketpair.h"
/*********************************************************************** /***********************************************************************
* Only for threaded name resolves builds * Only for threaded name resolves builds
@ -41,19 +44,8 @@
#include <inet.h> #include <inet.h>
#endif #endif
#if defined(USE_THREADS_POSIX) #if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
# ifdef HAVE_PTHREAD_H # include <pthread.h>
# include <pthread.h>
# endif
#elif defined(USE_THREADS_WIN32)
# ifdef HAVE_PROCESS_H
# include <process.h>
# endif
#endif
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
#undef in_addr_t
#define in_addr_t unsigned long
#endif #endif
#ifdef HAVE_GETADDRINFO #ifdef HAVE_GETADDRINFO
@ -67,10 +59,8 @@
#include "hostip.h" #include "hostip.h"
#include "hash.h" #include "hash.h"
#include "share.h" #include "share.h"
#include "strerror.h"
#include "url.h" #include "url.h"
#include "multiif.h" #include "multiif.h"
#include "inet_pton.h"
#include "inet_ntop.h" #include "inet_ntop.h"
#include "curl_threads.h" #include "curl_threads.h"
#include "connect.h" #include "connect.h"
@ -144,27 +134,30 @@ static void destroy_async_data(struct Curl_async *);
/* /*
* Cancel all possibly still on-going resolves for this connection. * Cancel all possibly still on-going resolves for this connection.
*/ */
void Curl_resolver_cancel(struct connectdata *conn) void Curl_resolver_cancel(struct Curl_easy *data)
{ {
destroy_async_data(&conn->async); destroy_async_data(&data->state.async);
} }
/* This function is used to init a threaded resolve */ /* This function is used to init a threaded resolve */
static bool init_resolve_thread(struct connectdata *conn, static bool init_resolve_thread(struct Curl_easy *data,
const char *hostname, int port, const char *hostname, int port,
const struct addrinfo *hints); const struct addrinfo *hints);
/* Data for synchronization between resolver thread and its parent */ /* Data for synchronization between resolver thread and its parent */
struct thread_sync_data { struct thread_sync_data {
curl_mutex_t * mtx; curl_mutex_t *mtx;
int done; int done;
int port;
char *hostname; /* hostname to resolve, Curl_async.hostname char *hostname; /* hostname to resolve, Curl_async.hostname
duplicate */ duplicate */
int port; #ifndef CURL_DISABLE_SOCKETPAIR
struct Curl_easy *data;
curl_socket_t sock_pair[2]; /* socket pair */
#endif
int sock_error; int sock_error;
Curl_addrinfo *res; struct Curl_addrinfo *res;
#ifdef HAVE_GETADDRINFO #ifdef HAVE_GETADDRINFO
struct addrinfo hints; struct addrinfo hints;
#endif #endif
@ -174,18 +167,18 @@ struct thread_sync_data {
struct thread_data { struct thread_data {
curl_thread_t thread_hnd; curl_thread_t thread_hnd;
unsigned int poll_interval; unsigned int poll_interval;
time_t interval_end; timediff_t interval_end;
struct thread_sync_data tsd; struct thread_sync_data tsd;
}; };
static struct thread_sync_data *conn_thread_sync_data(struct connectdata *conn) static struct thread_sync_data *conn_thread_sync_data(struct Curl_easy *data)
{ {
return &(((struct thread_data *)conn->async.os_specific)->tsd); return &(data->state.async.tdata->tsd);
} }
/* Destroy resolver thread synchronization data */ /* Destroy resolver thread synchronization data */
static static
void destroy_thread_sync_data(struct thread_sync_data * tsd) void destroy_thread_sync_data(struct thread_sync_data *tsd)
{ {
if(tsd->mtx) { if(tsd->mtx) {
Curl_mutex_destroy(tsd->mtx); Curl_mutex_destroy(tsd->mtx);
@ -197,12 +190,21 @@ void destroy_thread_sync_data(struct thread_sync_data * tsd)
if(tsd->res) if(tsd->res)
Curl_freeaddrinfo(tsd->res); Curl_freeaddrinfo(tsd->res);
#ifndef CURL_DISABLE_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)); memset(tsd, 0, sizeof(*tsd));
} }
/* Initialize resolver thread synchronization data */ /* Initialize resolver thread synchronization data */
static static
int init_thread_sync_data(struct thread_data * td, int init_thread_sync_data(struct thread_data *td,
const char *hostname, const char *hostname,
int port, int port,
const struct addrinfo *hints) const struct addrinfo *hints)
@ -225,11 +227,19 @@ int init_thread_sync_data(struct thread_data * td,
#endif #endif
tsd->mtx = malloc(sizeof(curl_mutex_t)); tsd->mtx = malloc(sizeof(curl_mutex_t));
if(tsd->mtx == NULL) if(!tsd->mtx)
goto err_exit; goto err_exit;
Curl_mutex_init(tsd->mtx); Curl_mutex_init(tsd->mtx);
#ifndef CURL_DISABLE_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; tsd->sock_error = CURL_ASYNC_SUCCESS;
/* Copying hostname string because original can be destroyed by parent /* Copying hostname string because original can be destroyed by parent
@ -242,23 +252,28 @@ int init_thread_sync_data(struct thread_data * td,
return 1; return 1;
err_exit: err_exit:
/* Memory allocation failed */ #ifndef CURL_DISABLE_SOCKETPAIR
if(tsd->sock_pair[0] != CURL_SOCKET_BAD) {
sclose(tsd->sock_pair[0]);
tsd->sock_pair[0] = CURL_SOCKET_BAD;
}
#endif
destroy_thread_sync_data(tsd); destroy_thread_sync_data(tsd);
return 0; return 0;
} }
static int getaddrinfo_complete(struct connectdata *conn) static CURLcode getaddrinfo_complete(struct Curl_easy *data)
{ {
struct thread_sync_data *tsd = conn_thread_sync_data(conn); struct thread_sync_data *tsd = conn_thread_sync_data(data);
int rc; CURLcode result;
rc = Curl_addrinfo_callback(conn, tsd->sock_error, tsd->res); result = Curl_addrinfo_callback(data, tsd->sock_error, tsd->res);
/* The tsd->res structure has been copied to async.dns and perhaps the DNS /* The tsd->res structure has been copied to async.dns and perhaps the DNS
cache. Set our copy to NULL so destroy_thread_sync_data doesn't free it. cache. Set our copy to NULL so destroy_thread_sync_data doesn't free it.
*/ */
tsd->res = NULL; tsd->res = NULL;
return rc; return result;
} }
@ -272,16 +287,19 @@ static int getaddrinfo_complete(struct connectdata *conn)
*/ */
static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg) static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg)
{ {
struct thread_sync_data *tsd = (struct thread_sync_data*)arg; struct thread_sync_data *tsd = (struct thread_sync_data *)arg;
struct thread_data *td = tsd->td; struct thread_data *td = tsd->td;
char service[12]; char service[12];
int rc; int rc;
#ifndef CURL_DISABLE_SOCKETPAIR
char buf[1];
#endif
msnprintf(service, sizeof(service), "%d", tsd->port); msnprintf(service, sizeof(service), "%d", tsd->port);
rc = Curl_getaddrinfo_ex(tsd->hostname, service, &tsd->hints, &tsd->res); rc = Curl_getaddrinfo_ex(tsd->hostname, service, &tsd->hints, &tsd->res);
if(rc != 0) { if(rc) {
tsd->sock_error = SOCKERRNO?SOCKERRNO:rc; tsd->sock_error = SOCKERRNO?SOCKERRNO:rc;
if(tsd->sock_error == 0) if(tsd->sock_error == 0)
tsd->sock_error = RESOLVER_ENOMEM; tsd->sock_error = RESOLVER_ENOMEM;
@ -298,6 +316,16 @@ static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg)
free(td); free(td);
} }
else { else {
#ifndef CURL_DISABLE_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; tsd->done = 1;
Curl_mutex_release(tsd->mtx); Curl_mutex_release(tsd->mtx);
} }
@ -345,9 +373,13 @@ static unsigned int CURL_STDCALL gethostbyname_thread(void *arg)
*/ */
static void destroy_async_data(struct Curl_async *async) static void destroy_async_data(struct Curl_async *async)
{ {
if(async->os_specific) { if(async->tdata) {
struct thread_data *td = (struct thread_data*) async->os_specific; struct thread_data *td = async->tdata;
int done; int done;
#ifndef CURL_DISABLE_SOCKETPAIR
curl_socket_t sock_rd = td->tsd.sock_pair[0];
struct Curl_easy *data = td->tsd.data;
#endif
/* /*
* if the thread is still blocking in the resolve syscall, detach it and * if the thread is still blocking in the resolve syscall, detach it and
@ -367,10 +399,18 @@ static void destroy_async_data(struct Curl_async *async)
destroy_thread_sync_data(&td->tsd); destroy_thread_sync_data(&td->tsd);
free(async->os_specific); free(async->tdata);
} }
#ifndef CURL_DISABLE_SOCKETPAIR
/*
* ensure CURLMOPT_SOCKETFUNCTION fires CURL_POLL_REMOVE
* before the FD is invalidated to avoid EBADF on EPOLL_CTL_DEL
*/
Curl_multi_closed(data, sock_rd);
sclose(sock_rd);
#endif
} }
async->os_specific = NULL; async->tdata = NULL;
free(async->hostname); free(async->hostname);
async->hostname = NULL; async->hostname = NULL;
@ -382,32 +422,33 @@ static void destroy_async_data(struct Curl_async *async)
* *
* Returns FALSE in case of failure, otherwise TRUE. * Returns FALSE in case of failure, otherwise TRUE.
*/ */
static bool init_resolve_thread(struct connectdata *conn, static bool init_resolve_thread(struct Curl_easy *data,
const char *hostname, int port, const char *hostname, int port,
const struct addrinfo *hints) const struct addrinfo *hints)
{ {
struct thread_data *td = calloc(1, sizeof(struct thread_data)); struct thread_data *td = calloc(1, sizeof(struct thread_data));
int err = ENOMEM; int err = ENOMEM;
struct Curl_async *asp = &data->state.async;
conn->async.os_specific = (void *)td; data->state.async.tdata = td;
if(!td) if(!td)
goto errno_exit; goto errno_exit;
conn->async.port = port; asp->port = port;
conn->async.done = FALSE; asp->done = FALSE;
conn->async.status = 0; asp->status = 0;
conn->async.dns = NULL; asp->dns = NULL;
td->thread_hnd = curl_thread_t_null; td->thread_hnd = curl_thread_t_null;
if(!init_thread_sync_data(td, hostname, port, hints)) { if(!init_thread_sync_data(td, hostname, port, hints)) {
conn->async.os_specific = NULL; asp->tdata = NULL;
free(td); free(td);
goto errno_exit; goto errno_exit;
} }
free(conn->async.hostname); free(asp->hostname);
conn->async.hostname = strdup(hostname); asp->hostname = strdup(hostname);
if(!conn->async.hostname) if(!asp->hostname)
goto err_exit; goto err_exit;
/* The thread will set this to 1 when complete. */ /* The thread will set this to 1 when complete. */
@ -429,7 +470,7 @@ static bool init_resolve_thread(struct connectdata *conn,
return TRUE; return TRUE;
err_exit: err_exit:
destroy_async_data(&conn->async); destroy_async_data(asp);
errno_exit: errno_exit:
errno = err; errno = err;
@ -437,61 +478,41 @@ static bool init_resolve_thread(struct connectdata *conn,
} }
/* /*
* resolver_error() calls failf() with the appropriate message after a resolve * 'entry' may be NULL and then no data is returned
* error
*/ */
static CURLcode thread_wait_resolv(struct Curl_easy *data,
static CURLcode resolver_error(struct connectdata *conn)
{
const char *host_or_proxy;
CURLcode result;
if(conn->bits.httpproxy) {
host_or_proxy = "proxy";
result = CURLE_COULDNT_RESOLVE_PROXY;
}
else {
host_or_proxy = "host";
result = CURLE_COULDNT_RESOLVE_HOST;
}
failf(conn->data, "Could not resolve %s: %s", host_or_proxy,
conn->async.hostname);
return result;
}
static CURLcode thread_wait_resolv(struct connectdata *conn,
struct Curl_dns_entry **entry, struct Curl_dns_entry **entry,
bool report) bool report)
{ {
struct thread_data *td = (struct thread_data*) conn->async.os_specific; struct thread_data *td;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
DEBUGASSERT(conn && td); DEBUGASSERT(data);
td = data->state.async.tdata;
DEBUGASSERT(td);
DEBUGASSERT(td->thread_hnd != curl_thread_t_null); DEBUGASSERT(td->thread_hnd != curl_thread_t_null);
/* wait for the thread to resolve the name */ /* wait for the thread to resolve the name */
if(Curl_thread_join(&td->thread_hnd)) { if(Curl_thread_join(&td->thread_hnd)) {
if(entry) if(entry)
result = getaddrinfo_complete(conn); result = getaddrinfo_complete(data);
} }
else else
DEBUGASSERT(0); DEBUGASSERT(0);
conn->async.done = TRUE; data->state.async.done = TRUE;
if(entry) if(entry)
*entry = conn->async.dns; *entry = data->state.async.dns;
if(!conn->async.dns && report) if(!data->state.async.dns && report)
/* a name was not resolved, report error */ /* a name was not resolved, report error */
result = resolver_error(conn); result = Curl_resolver_error(data);
destroy_async_data(&conn->async); destroy_async_data(&data->state.async);
if(!conn->async.dns && report) if(!data->state.async.dns && report)
connclose(conn, "asynch resolve failed"); connclose(data->conn, "asynch resolve failed");
return result; return result;
} }
@ -501,17 +522,18 @@ static CURLcode thread_wait_resolv(struct connectdata *conn,
* Until we gain a way to signal the resolver threads to stop early, we must * Until we gain a way to signal the resolver threads to stop early, we must
* simply wait for them and ignore their results. * simply wait for them and ignore their results.
*/ */
void Curl_resolver_kill(struct connectdata *conn) void Curl_resolver_kill(struct Curl_easy *data)
{ {
struct thread_data *td = (struct thread_data*) conn->async.os_specific; struct thread_data *td = data->state.async.tdata;
/* If we're still resolving, we must wait for the threads to fully clean up, /* If we're still resolving, we must wait for the threads to fully clean up,
unfortunately. Otherwise, we can simply cancel to clean up any resolver unfortunately. Otherwise, we can simply cancel to clean up any resolver
data. */ data. */
if(td && td->thread_hnd != curl_thread_t_null) if(td && td->thread_hnd != curl_thread_t_null
(void)thread_wait_resolv(conn, NULL, FALSE); && (data->set.quick_exit != 1L))
(void)thread_wait_resolv(data, NULL, FALSE);
else else
Curl_resolver_cancel(conn); Curl_resolver_cancel(data);
} }
/* /*
@ -527,10 +549,10 @@ void Curl_resolver_kill(struct connectdata *conn)
* *
* This is the version for resolves-in-a-thread. * This is the version for resolves-in-a-thread.
*/ */
CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
struct Curl_dns_entry **entry) struct Curl_dns_entry **entry)
{ {
return thread_wait_resolv(conn, entry, TRUE); return thread_wait_resolv(data, entry, TRUE);
} }
/* /*
@ -538,13 +560,13 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
* name resolve request has completed. It should also make sure to time-out if * name resolve request has completed. It should also make sure to time-out if
* the operation seems to take too long. * the operation seems to take too long.
*/ */
CURLcode Curl_resolver_is_resolved(struct connectdata *conn, CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
struct Curl_dns_entry **entry) struct Curl_dns_entry **entry)
{ {
struct Curl_easy *data = conn->data; struct thread_data *td = data->state.async.tdata;
struct thread_data *td = (struct thread_data*) conn->async.os_specific;
int done = 0; int done = 0;
DEBUGASSERT(entry);
*entry = NULL; *entry = NULL;
if(!td) { if(!td) {
@ -557,18 +579,19 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
Curl_mutex_release(td->tsd.mtx); Curl_mutex_release(td->tsd.mtx);
if(done) { if(done) {
getaddrinfo_complete(conn); getaddrinfo_complete(data);
if(!conn->async.dns) { if(!data->state.async.dns) {
CURLcode result = resolver_error(conn); CURLcode result = Curl_resolver_error(data);
destroy_async_data(&conn->async); destroy_async_data(&data->state.async);
return result; return result;
} }
destroy_async_data(&conn->async); destroy_async_data(&data->state.async);
*entry = conn->async.dns; *entry = data->state.async.dns;
} }
else { else {
/* poll for name lookup done with exponential backoff up to 250ms */ /* poll for name lookup done with exponential backoff up to 250ms */
/* should be fine even if this converts to 32 bit */
timediff_t elapsed = Curl_timediff(Curl_now(), timediff_t elapsed = Curl_timediff(Curl_now(),
data->progress.t_startsingle); data->progress.t_startsingle);
if(elapsed < 0) if(elapsed < 0)
@ -585,63 +608,73 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
td->poll_interval = 250; td->poll_interval = 250;
td->interval_end = elapsed + td->poll_interval; td->interval_end = elapsed + td->poll_interval;
Curl_expire(conn->data, td->poll_interval, EXPIRE_ASYNC_NAME); Curl_expire(data, td->poll_interval, EXPIRE_ASYNC_NAME);
} }
return CURLE_OK; return CURLE_OK;
} }
int Curl_resolver_getsock(struct connectdata *conn, int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *socks)
curl_socket_t *socks,
int numsocks)
{ {
time_t milli; int ret_val = 0;
timediff_t milli;
timediff_t ms; timediff_t ms;
struct Curl_easy *data = conn->data; struct resdata *reslv = (struct resdata *)data->state.async.resolver;
struct resdata *reslv = (struct resdata *)data->state.resolver; #ifndef CURL_DISABLE_SOCKETPAIR
struct thread_data *td = data->state.async.tdata;
#else
(void)socks; (void)socks;
(void)numsocks; #endif
ms = Curl_timediff(Curl_now(), reslv->start);
if(ms < 3) #ifndef CURL_DISABLE_SOCKETPAIR
milli = 0; if(td) {
else if(ms <= 50) /* return read fd to client for polling the DNS resolution status */
milli = ms/3; socks[0] = td->tsd.sock_pair[0];
else if(ms <= 250) td->tsd.data = data;
milli = 50; ret_val = GETSOCK_READSOCK(0);
else }
milli = 200; else {
Curl_expire(data, milli, EXPIRE_ASYNC_NAME); #endif
return 0; 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);
#ifndef CURL_DISABLE_SOCKETPAIR
}
#endif
return ret_val;
} }
#ifndef HAVE_GETADDRINFO #ifndef HAVE_GETADDRINFO
/* /*
* Curl_getaddrinfo() - for platforms without getaddrinfo * Curl_getaddrinfo() - for platforms without getaddrinfo
*/ */
Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
const char *hostname, const char *hostname,
int port, int port,
int *waitp) int *waitp)
{ {
struct in_addr in; struct resdata *reslv = (struct resdata *)data->state.async.resolver;
struct Curl_easy *data = conn->data;
struct resdata *reslv = (struct resdata *)data->state.resolver;
*waitp = 0; /* default to synchronous response */ *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(); reslv->start = Curl_now();
/* fire up a new resolver thread! */ /* fire up a new resolver thread! */
if(init_resolve_thread(conn, hostname, port, NULL)) { if(init_resolve_thread(data, hostname, port, NULL)) {
*waitp = 1; /* expect asynchronous response */ *waitp = 1; /* expect asynchronous response */
return NULL; return NULL;
} }
failf(conn->data, "getaddrinfo() thread failed\n"); failf(data, "getaddrinfo() thread failed");
return NULL; return NULL;
} }
@ -651,73 +684,36 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
/* /*
* Curl_resolver_getaddrinfo() - for getaddrinfo * Curl_resolver_getaddrinfo() - for getaddrinfo
*/ */
Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
const char *hostname, const char *hostname,
int port, int port,
int *waitp) int *waitp)
{ {
struct addrinfo hints; struct addrinfo hints;
char sbuf[12];
int pf = PF_INET; int pf = PF_INET;
struct Curl_easy *data = conn->data; struct resdata *reslv = (struct resdata *)data->state.async.resolver;
struct resdata *reslv = (struct resdata *)data->state.resolver;
*waitp = 0; /* default to synchronous response */ *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 #ifdef CURLRES_IPV6
{ if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data))
struct in6_addr in6; /* The stack seems to be IPv6-enabled */
/* 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.
*/
switch(conn->ip_version) {
case CURL_IPRESOLVE_V4:
pf = PF_INET;
break;
case CURL_IPRESOLVE_V6:
pf = PF_INET6;
break;
default:
pf = PF_UNSPEC; pf = PF_UNSPEC;
break;
}
if((pf != PF_INET) && !Curl_ipv6works())
/* The stack seems to be a non-IPv6 one */
pf = PF_INET;
#endif /* CURLRES_IPV6 */ #endif /* CURLRES_IPV6 */
memset(&hints, 0, sizeof(hints)); memset(&hints, 0, sizeof(hints));
hints.ai_family = pf; hints.ai_family = pf;
hints.ai_socktype = conn->socktype; hints.ai_socktype = (data->conn->transport == TRNSPRT_TCP)?
SOCK_STREAM : SOCK_DGRAM;
msnprintf(sbuf, sizeof(sbuf), "%d", port);
reslv->start = Curl_now(); reslv->start = Curl_now();
/* fire up a new resolver thread! */ /* fire up a new resolver thread! */
if(init_resolve_thread(conn, hostname, port, &hints)) { if(init_resolve_thread(data, hostname, port, &hints)) {
*waitp = 1; /* expect asynchronous response */ *waitp = 1; /* expect asynchronous response */
return NULL; return NULL;
} }
failf(data, "getaddrinfo() thread failed to start\n"); failf(data, "getaddrinfo() thread failed to start");
return NULL; return NULL;
} }

View file

@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#include "curl_setup.h" #include "curl_setup.h"
@ -91,7 +93,7 @@ CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to,
* *
* It is safe to call this when conn is in any state. * It is safe to call this when conn is in any state.
*/ */
void Curl_resolver_cancel(struct connectdata *conn); void Curl_resolver_cancel(struct Curl_easy *data);
/* /*
* Curl_resolver_kill(). * Curl_resolver_kill().
@ -104,7 +106,7 @@ void Curl_resolver_cancel(struct connectdata *conn);
* *
* It is safe to call this when conn is in any state. * It is safe to call this when conn is in any state.
*/ */
void Curl_resolver_kill(struct connectdata *conn); void Curl_resolver_kill(struct Curl_easy *data);
/* Curl_resolver_getsock() /* Curl_resolver_getsock()
* *
@ -114,8 +116,7 @@ void Curl_resolver_kill(struct connectdata *conn);
* return bitmask indicating what file descriptors (referring to array indexes * return bitmask indicating what file descriptors (referring to array indexes
* in the 'sock' array) to wait for, read/write. * in the 'sock' array) to wait for, read/write.
*/ */
int Curl_resolver_getsock(struct connectdata *conn, curl_socket_t *sock, int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *sock);
int numsocks);
/* /*
* Curl_resolver_is_resolved() * Curl_resolver_is_resolved()
@ -126,7 +127,7 @@ int Curl_resolver_getsock(struct connectdata *conn, curl_socket_t *sock,
* *
* Returns normal CURLcode errors. * Returns normal CURLcode errors.
*/ */
CURLcode Curl_resolver_is_resolved(struct connectdata *conn, CURLcode Curl_resolver_is_resolved(struct Curl_easy *data,
struct Curl_dns_entry **dns); struct Curl_dns_entry **dns);
/* /*
@ -140,24 +141,24 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
* Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved,
* CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors. * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
*/ */
CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data,
struct Curl_dns_entry **dnsentry); struct Curl_dns_entry **dnsentry);
/* /*
* Curl_resolver_getaddrinfo() - when using this resolver * Curl_resolver_getaddrinfo() - when using this resolver
* *
* Returns name information about the given hostname and port number. If * Returns name information about the given hostname and port number. If
* successful, the 'hostent' is returned and the forth argument will point to * successful, the 'hostent' is returned and the fourth argument will point to
* memory we need to free after use. That memory *MUST* be freed with * memory we need to free after use. That memory *MUST* be freed with
* Curl_freeaddrinfo(), nothing else. * Curl_freeaddrinfo(), nothing else.
* *
* Each resolver backend must of course make sure to return data in the * Each resolver backend must of course make sure to return data in the
* correct format to comply with this. * correct format to comply with this.
*/ */
Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
const char *hostname, const char *hostname,
int port, int port,
int *waitp); int *waitp);
#ifndef CURLRES_ASYNCH #ifndef CURLRES_ASYNCH
/* convert these functions if an asynch resolver isn't used */ /* convert these functions if an asynch resolver isn't used */
@ -165,7 +166,6 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
#define Curl_resolver_kill(x) Curl_nop_stmt #define Curl_resolver_kill(x) Curl_nop_stmt
#define Curl_resolver_is_resolved(x,y) CURLE_COULDNT_RESOLVE_HOST #define Curl_resolver_is_resolved(x,y) CURLE_COULDNT_RESOLVE_HOST
#define Curl_resolver_wait_resolv(x,y) CURLE_COULDNT_RESOLVE_HOST #define Curl_resolver_wait_resolv(x,y) CURLE_COULDNT_RESOLVE_HOST
#define Curl_resolver_getsock(x,y,z) 0
#define Curl_resolver_duphandle(x,y,z) CURLE_OK #define Curl_resolver_duphandle(x,y,z) CURLE_OK
#define Curl_resolver_init(x,y) CURLE_OK #define Curl_resolver_init(x,y) CURLE_OK
#define Curl_resolver_global_init() CURLE_OK #define Curl_resolver_global_init() CURLE_OK

View file

@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -18,75 +18,45 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
/* Base64 encoding/decoding */ /* Base64 encoding/decoding */
#include "curl_setup.h" #include "curl_setup.h"
#if !defined(CURL_DISABLE_HTTP_AUTH) || defined(USE_LIBSSH2) || \ #if !defined(CURL_DISABLE_HTTP_AUTH) || defined(USE_SSH) || \
defined(USE_LIBSSH) || !defined(CURL_DISABLE_LDAP) || \ !defined(CURL_DISABLE_LDAP) || \
!defined(CURL_DISABLE_SMTP) || \
!defined(CURL_DISABLE_POP3) || \
!defined(CURL_DISABLE_IMAP) || \
!defined(CURL_DISABLE_DOH) || defined(USE_SSL) !defined(CURL_DISABLE_DOH) || defined(USE_SSL)
#include "urldata.h" /* for the Curl_easy definition */ #include "urldata.h" /* for the Curl_easy definition */
#include "warnless.h" #include "warnless.h"
#include "curl_base64.h" #include "curl_base64.h"
#include "non-ascii.h"
/* The last 3 #include files should be in this order */ /* The last 2 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h" #include "curl_memory.h"
#include "memdebug.h" #include "memdebug.h"
/* ---- Base64 Encoding/Decoding Table --- */ /* ---- Base64 Encoding/Decoding Table --- */
/* Padding character string starts at offset 64. */
static const char base64[]= static const char base64[]=
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
/* The Base 64 encoding with an URL and filename safe alphabet, RFC 4648 /* The Base 64 encoding with a URL and filename safe alphabet, RFC 4648
section 5 */ section 5 */
static const char base64url[]= static const char base64url[]=
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
static size_t decodeQuantum(unsigned char *dest, const char *src) static const unsigned char decodetable[] =
{ { 62, 255, 255, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255,
size_t padding = 0; 255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
const char *s, *p; 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255, 255, 26, 27, 28,
unsigned long i, x = 0; 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51 };
for(i = 0, s = src; i < 4; i++, s++) {
if(*s == '=') {
x = (x << 6);
padding++;
}
else {
unsigned long v = 0;
p = base64;
while(*p && (*p != *s)) {
v++;
p++;
}
if(*p == *s)
x = (x << 6) + v;
else
return 0;
}
}
if(padding < 1)
dest[2] = curlx_ultouc(x & 0xFFUL);
x >>= 8;
if(padding < 2)
dest[1] = curlx_ultouc(x & 0xFFUL);
x >>= 8;
dest[0] = curlx_ultouc(x & 0xFFUL);
return 3 - padding;
}
/* /*
* Curl_base64_decode() * Curl_base64_decode()
* *
@ -105,13 +75,14 @@ CURLcode Curl_base64_decode(const char *src,
unsigned char **outptr, size_t *outlen) unsigned char **outptr, size_t *outlen)
{ {
size_t srclen = 0; size_t srclen = 0;
size_t length = 0;
size_t padding = 0; size_t padding = 0;
size_t i; size_t i;
size_t numQuantums; size_t numQuantums;
size_t fullQuantums;
size_t rawlen = 0; size_t rawlen = 0;
unsigned char *pos; unsigned char *pos;
unsigned char *newstr; unsigned char *newstr;
unsigned char lookup[256];
*outptr = NULL; *outptr = NULL;
*outlen = 0; *outlen = 0;
@ -121,45 +92,82 @@ CURLcode Curl_base64_decode(const char *src,
if(!srclen || srclen % 4) if(!srclen || srclen % 4)
return CURLE_BAD_CONTENT_ENCODING; return CURLE_BAD_CONTENT_ENCODING;
/* Find the position of any = padding characters */ /* srclen is at least 4 here */
while((src[length] != '=') && src[length]) while(src[srclen - 1 - padding] == '=') {
length++; /* count padding characters */
/* A maximum of two = padding characters is allowed */
if(src[length] == '=') {
padding++; padding++;
if(src[length + 1] == '=') /* A maximum of two = padding characters is allowed */
padding++; if(padding > 2)
return CURLE_BAD_CONTENT_ENCODING;
} }
/* Check the = padding characters weren't part way through the input */
if(length + padding != srclen)
return CURLE_BAD_CONTENT_ENCODING;
/* Calculate the number of quantums */ /* Calculate the number of quantums */
numQuantums = srclen / 4; numQuantums = srclen / 4;
fullQuantums = numQuantums - (padding ? 1 : 0);
/* Calculate the size of the decoded string */ /* Calculate the size of the decoded string */
rawlen = (numQuantums * 3) - padding; rawlen = (numQuantums * 3) - padding;
/* Allocate our buffer including room for a zero terminator */ /* Allocate our buffer including room for a null-terminator */
newstr = malloc(rawlen + 1); newstr = malloc(rawlen + 1);
if(!newstr) if(!newstr)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
pos = newstr; pos = newstr;
/* Decode the quantums */ memset(lookup, 0xff, sizeof(lookup));
for(i = 0; i < numQuantums; i++) { memcpy(&lookup['+'], decodetable, sizeof(decodetable));
size_t result = decodeQuantum(pos, src); /* replaces
if(!result) { {
free(newstr); unsigned char c;
const unsigned char *p = (const unsigned char *)base64;
for(c = 0; *p; c++, p++)
lookup[*p] = c;
}
*/
return CURLE_BAD_CONTENT_ENCODING; /* Decode the complete quantums first */
for(i = 0; i < fullQuantums; i++) {
unsigned char val;
unsigned int x = 0;
int j;
for(j = 0; j < 4; j++) {
val = lookup[(unsigned char)*src++];
if(val == 0xff) /* bad symbol */
goto bad;
x = (x << 6) | val;
} }
pos[2] = x & 0xff;
pos += result; pos[1] = (x >> 8) & 0xff;
src += 4; pos[0] = (x >> 16) & 0xff;
pos += 3;
}
if(padding) {
/* this means either 8 or 16 bits output */
unsigned char val;
unsigned int x = 0;
int j;
size_t padc = 0;
for(j = 0; j < 4; j++) {
if(*src == '=') {
x <<= 6;
src++;
if(++padc > padding)
/* this is a badly placed '=' symbol! */
goto bad;
}
else {
val = lookup[(unsigned char)*src++];
if(val == 0xff) /* bad symbol */
goto bad;
x = (x << 6) | val;
}
}
if(padding == 1)
pos[1] = (x >> 8) & 0xff;
pos[0] = (x >> 16) & 0xff;
pos += 3 - padding;
} }
/* Zero terminate */ /* Zero terminate */
@ -170,95 +178,60 @@ CURLcode Curl_base64_decode(const char *src,
*outlen = rawlen; *outlen = rawlen;
return CURLE_OK; return CURLE_OK;
bad:
free(newstr);
return CURLE_BAD_CONTENT_ENCODING;
} }
static CURLcode base64_encode(const char *table64, static CURLcode base64_encode(const char *table64,
struct Curl_easy *data,
const char *inputbuff, size_t insize, const char *inputbuff, size_t insize,
char **outptr, size_t *outlen) char **outptr, size_t *outlen)
{ {
CURLcode result;
unsigned char ibuf[3];
unsigned char obuf[4];
int i;
int inputparts;
char *output; char *output;
char *base64data; char *base64data;
char *convbuf = NULL; const unsigned char *in = (unsigned char *)inputbuff;
const char *padstr = &table64[64]; /* Point to padding string. */
const char *indata = inputbuff;
*outptr = NULL; *outptr = NULL;
*outlen = 0; *outlen = 0;
if(!insize) if(!insize)
insize = strlen(indata); insize = strlen(inputbuff);
#if SIZEOF_SIZE_T == 4 #if SIZEOF_SIZE_T == 4
if(insize > UINT_MAX/4) if(insize > UINT_MAX/4)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
#endif #endif
base64data = output = malloc(insize * 4 / 3 + 4); base64data = output = malloc((insize + 2) / 3 * 4 + 1);
if(!output) if(!output)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
/* while(insize >= 3) {
* The base64 data needs to be created using the network encoding *output++ = table64[ in[0] >> 2 ];
* not the host encoding. And we can't change the actual input *output++ = table64[ ((in[0] & 0x03) << 4) | (in[1] >> 4) ];
* so we copy it to a buffer, translate it, and use that instead. *output++ = table64[ ((in[1] & 0x0F) << 2) | ((in[2] & 0xC0) >> 6) ];
*/ *output++ = table64[ in[2] & 0x3F ];
result = Curl_convert_clone(data, indata, insize, &convbuf); insize -= 3;
if(result) { in += 3;
free(output);
return result;
} }
if(insize) {
if(convbuf) /* this is only one or two bytes now */
indata = (char *)convbuf; *output++ = table64[ in[0] >> 2 ];
if(insize == 1) {
while(insize > 0) { *output++ = table64[ ((in[0] & 0x03) << 4) ];
for(i = inputparts = 0; i < 3; i++) { if(*padstr) {
if(insize > 0) { *output++ = *padstr;
inputparts++; *output++ = *padstr;
ibuf[i] = (unsigned char) *indata;
indata++;
insize--;
} }
else
ibuf[i] = 0;
} }
else {
obuf[0] = (unsigned char) ((ibuf[0] & 0xFC) >> 2); /* insize == 2 */
obuf[1] = (unsigned char) (((ibuf[0] & 0x03) << 4) | \ *output++ = table64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xF0) >> 4) ];
((ibuf[1] & 0xF0) >> 4)); *output++ = table64[ ((in[1] & 0x0F) << 2) ];
obuf[2] = (unsigned char) (((ibuf[1] & 0x0F) << 2) | \ if(*padstr)
((ibuf[2] & 0xC0) >> 6)); *output++ = *padstr;
obuf[3] = (unsigned char) (ibuf[2] & 0x3F);
switch(inputparts) {
case 1: /* only one byte read */
msnprintf(output, 5, "%c%c==",
table64[obuf[0]],
table64[obuf[1]]);
break;
case 2: /* two bytes read */
msnprintf(output, 5, "%c%c%c=",
table64[obuf[0]],
table64[obuf[1]],
table64[obuf[2]]);
break;
default:
msnprintf(output, 5, "%c%c%c%c",
table64[obuf[0]],
table64[obuf[1]],
table64[obuf[2]],
table64[obuf[3]]);
break;
} }
output += 4;
} }
/* Zero terminate */ /* Zero terminate */
@ -267,10 +240,8 @@ static CURLcode base64_encode(const char *table64,
/* Return the pointer to the new data (allocated memory) */ /* Return the pointer to the new data (allocated memory) */
*outptr = base64data; *outptr = base64data;
free(convbuf);
/* Return the length of the new data */ /* Return the length of the new data */
*outlen = strlen(base64data); *outlen = output - base64data;
return CURLE_OK; return CURLE_OK;
} }
@ -288,15 +259,12 @@ static CURLcode base64_encode(const char *table64,
* Returns CURLE_OK on success, otherwise specific error code. Function * Returns CURLE_OK on success, otherwise specific error code. Function
* output shall not be considered valid unless CURLE_OK is returned. * output shall not be considered valid unless CURLE_OK is returned.
* *
* When encoded data length is 0, returns NULL in *outptr.
*
* @unittest: 1302 * @unittest: 1302
*/ */
CURLcode Curl_base64_encode(struct Curl_easy *data, CURLcode Curl_base64_encode(const char *inputbuff, size_t insize,
const char *inputbuff, size_t insize,
char **outptr, size_t *outlen) char **outptr, size_t *outlen)
{ {
return base64_encode(base64, data, inputbuff, insize, outptr, outlen); return base64_encode(base64, inputbuff, insize, outptr, outlen);
} }
/* /*
@ -312,15 +280,12 @@ CURLcode Curl_base64_encode(struct Curl_easy *data,
* Returns CURLE_OK on success, otherwise specific error code. Function * Returns CURLE_OK on success, otherwise specific error code. Function
* output shall not be considered valid unless CURLE_OK is returned. * output shall not be considered valid unless CURLE_OK is returned.
* *
* When encoded data length is 0, returns NULL in *outptr.
*
* @unittest: 1302 * @unittest: 1302
*/ */
CURLcode Curl_base64url_encode(struct Curl_easy *data, CURLcode Curl_base64url_encode(const char *inputbuff, size_t insize,
const char *inputbuff, size_t insize,
char **outptr, size_t *outlen) char **outptr, size_t *outlen)
{ {
return base64_encode(base64url, data, inputbuff, insize, outptr, outlen); return base64_encode(base64url, inputbuff, insize, outptr, outlen);
} }
#endif /* no users so disabled */ #endif /* no users so disabled */

View file

@ -0,0 +1,129 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#include "urldata.h"
#include "bufref.h"
#include "curl_memory.h"
#include "memdebug.h"
#define SIGNATURE 0x5c48e9b2 /* Random pattern. */
/*
* Init a bufref struct.
*/
void Curl_bufref_init(struct bufref *br)
{
DEBUGASSERT(br);
br->dtor = NULL;
br->ptr = NULL;
br->len = 0;
#ifdef DEBUGBUILD
br->signature = SIGNATURE;
#endif
}
/*
* Free the buffer and re-init the necessary fields. It doesn't touch the
* 'signature' field and thus this buffer reference can be reused.
*/
void Curl_bufref_free(struct bufref *br)
{
DEBUGASSERT(br);
DEBUGASSERT(br->signature == SIGNATURE);
DEBUGASSERT(br->ptr || !br->len);
if(br->ptr && br->dtor)
br->dtor((void *) br->ptr);
br->dtor = NULL;
br->ptr = NULL;
br->len = 0;
}
/*
* Set the buffer reference to new values. The previously referenced buffer
* is released before assignment.
*/
void Curl_bufref_set(struct bufref *br, const void *ptr, size_t len,
void (*dtor)(void *))
{
DEBUGASSERT(ptr || !len);
DEBUGASSERT(len <= CURL_MAX_INPUT_LENGTH);
Curl_bufref_free(br);
br->ptr = (const unsigned char *) ptr;
br->len = len;
br->dtor = dtor;
}
/*
* Get a pointer to the referenced buffer.
*/
const unsigned char *Curl_bufref_ptr(const struct bufref *br)
{
DEBUGASSERT(br);
DEBUGASSERT(br->signature == SIGNATURE);
DEBUGASSERT(br->ptr || !br->len);
return br->ptr;
}
/*
* Get the length of the referenced buffer data.
*/
size_t Curl_bufref_len(const struct bufref *br)
{
DEBUGASSERT(br);
DEBUGASSERT(br->signature == SIGNATURE);
DEBUGASSERT(br->ptr || !br->len);
return br->len;
}
CURLcode Curl_bufref_memdup(struct bufref *br, const void *ptr, size_t len)
{
unsigned char *cpy = NULL;
DEBUGASSERT(br);
DEBUGASSERT(br->signature == SIGNATURE);
DEBUGASSERT(br->ptr || !br->len);
DEBUGASSERT(ptr || !len);
DEBUGASSERT(len <= CURL_MAX_INPUT_LENGTH);
if(ptr) {
cpy = malloc(len + 1);
if(!cpy)
return CURLE_OUT_OF_MEMORY;
if(len)
memcpy(cpy, ptr, len);
cpy[len] = '\0';
}
Curl_bufref_set(br, cpy, len, curl_free);
return CURLE_OK;
}

View file

@ -0,0 +1,48 @@
#ifndef HEADER_CURL_BUFREF_H
#define HEADER_CURL_BUFREF_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
/*
* Generic buffer reference.
*/
struct bufref {
void (*dtor)(void *); /* Associated destructor. */
const unsigned char *ptr; /* Referenced data buffer. */
size_t len; /* The data size in bytes. */
#ifdef DEBUGBUILD
int signature; /* Detect API use mistakes. */
#endif
};
void Curl_bufref_init(struct bufref *br);
void Curl_bufref_set(struct bufref *br, const void *ptr, size_t len,
void (*dtor)(void *));
const unsigned char *Curl_bufref_ptr(const struct bufref *br);
size_t Curl_bufref_len(const struct bufref *br);
CURLcode Curl_bufref_memdup(struct bufref *br, const void *ptr, size_t len);
void Curl_bufref_free(struct bufref *br);
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,60 @@
#ifndef HEADER_CURL_HYPER_H
#define HEADER_CURL_HYPER_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#if !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER)
#include <hyper.h>
/* per-transfer data for the Hyper backend */
struct hyptransfer {
hyper_waker *write_waker;
hyper_waker *read_waker;
const hyper_executor *exec;
hyper_task *endtask;
hyper_waker *exp100_waker;
hyper_waker *send_body_waker;
};
size_t Curl_hyper_recv(void *userp, hyper_context *ctx,
uint8_t *buf, size_t buflen);
size_t Curl_hyper_send(void *userp, hyper_context *ctx,
const uint8_t *buf, size_t buflen);
CURLcode Curl_hyper_stream(struct Curl_easy *data,
struct connectdata *conn,
int *didwhat,
bool *done,
int select_res);
CURLcode Curl_hyper_header(struct Curl_easy *data, hyper_headers *headers,
const char *line);
void Curl_hyper_done(struct Curl_easy *);
#else
#define Curl_hyper_done(x)
#endif /* !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER) */
#endif /* HEADER_CURL_HYPER_H */

View file

@ -0,0 +1,569 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#if !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER)
#include "urldata.h"
#include <curl/curl.h>
#include "curl_log.h"
#include "cfilters.h"
#include "connect.h"
#include "multiif.h"
#include "cf-https-connect.h"
#include "http2.h"
#include "vquic/vquic.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
typedef enum {
CF_HC_INIT,
CF_HC_CONNECT,
CF_HC_SUCCESS,
CF_HC_FAILURE
} cf_hc_state;
struct cf_hc_baller {
const char *name;
struct Curl_cfilter *cf;
CURLcode result;
struct curltime started;
int reply_ms;
bool enabled;
};
static void cf_hc_baller_reset(struct cf_hc_baller *b,
struct Curl_easy *data)
{
if(b->cf) {
Curl_conn_cf_close(b->cf, data);
Curl_conn_cf_discard_chain(&b->cf, data);
b->cf = NULL;
}
b->result = CURLE_OK;
b->reply_ms = -1;
}
static bool cf_hc_baller_is_active(struct cf_hc_baller *b)
{
return b->enabled && b->cf && !b->result;
}
static bool cf_hc_baller_has_started(struct cf_hc_baller *b)
{
return !!b->cf;
}
static int cf_hc_baller_reply_ms(struct cf_hc_baller *b,
struct Curl_easy *data)
{
if(b->reply_ms < 0)
b->cf->cft->query(b->cf, data, CF_QUERY_CONNECT_REPLY_MS,
&b->reply_ms, NULL);
return b->reply_ms;
}
static bool cf_hc_baller_data_pending(struct cf_hc_baller *b,
const struct Curl_easy *data)
{
return b->cf && !b->result && b->cf->cft->has_data_pending(b->cf, data);
}
struct cf_hc_ctx {
cf_hc_state state;
const struct Curl_dns_entry *remotehost;
struct curltime started; /* when connect started */
CURLcode result; /* overall result */
struct cf_hc_baller h3_baller;
struct cf_hc_baller h21_baller;
int soft_eyeballs_timeout_ms;
int hard_eyeballs_timeout_ms;
};
static void cf_hc_baller_init(struct cf_hc_baller *b,
struct Curl_cfilter *cf,
struct Curl_easy *data,
const char *name,
int transport)
{
struct cf_hc_ctx *ctx = cf->ctx;
struct Curl_cfilter *save = cf->next;
b->name = name;
cf->next = NULL;
b->started = Curl_now();
b->result = Curl_cf_setup_insert_after(cf, data, ctx->remotehost,
transport, CURL_CF_SSL_ENABLE);
b->cf = cf->next;
cf->next = save;
}
static CURLcode cf_hc_baller_connect(struct cf_hc_baller *b,
struct Curl_cfilter *cf,
struct Curl_easy *data,
bool *done)
{
struct Curl_cfilter *save = cf->next;
cf->next = b->cf;
b->result = Curl_conn_cf_connect(cf->next, data, FALSE, done);
b->cf = cf->next; /* it might mutate */
cf->next = save;
return b->result;
}
static void cf_hc_reset(struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct cf_hc_ctx *ctx = cf->ctx;
if(ctx) {
cf_hc_baller_reset(&ctx->h3_baller, data);
cf_hc_baller_reset(&ctx->h21_baller, data);
ctx->state = CF_HC_INIT;
ctx->result = CURLE_OK;
ctx->hard_eyeballs_timeout_ms = data->set.happy_eyeballs_timeout;
ctx->soft_eyeballs_timeout_ms = data->set.happy_eyeballs_timeout / 2;
}
}
static CURLcode baller_connected(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct cf_hc_baller *winner)
{
struct cf_hc_ctx *ctx = cf->ctx;
CURLcode result = CURLE_OK;
DEBUGASSERT(winner->cf);
if(winner != &ctx->h3_baller)
cf_hc_baller_reset(&ctx->h3_baller, data);
if(winner != &ctx->h21_baller)
cf_hc_baller_reset(&ctx->h21_baller, data);
DEBUGF(LOG_CF(data, cf, "connect+handshake %s: %dms, 1st data: %dms",
winner->name, (int)Curl_timediff(Curl_now(), winner->started),
cf_hc_baller_reply_ms(winner, data)));
cf->next = winner->cf;
winner->cf = NULL;
switch(cf->conn->alpn) {
case CURL_HTTP_VERSION_3:
infof(data, "using HTTP/3");
break;
case CURL_HTTP_VERSION_2:
#ifdef USE_NGHTTP2
/* Using nghttp2, we add the filter "below" us, so when the conn
* closes, we tear it down for a fresh reconnect */
result = Curl_http2_switch_at(cf, data);
if(result) {
ctx->state = CF_HC_FAILURE;
ctx->result = result;
return result;
}
#endif
infof(data, "using HTTP/2");
break;
case CURL_HTTP_VERSION_1_1:
infof(data, "using HTTP/1.1");
break;
default:
infof(data, "using HTTP/1.x");
break;
}
ctx->state = CF_HC_SUCCESS;
cf->connected = TRUE;
Curl_conn_cf_cntrl(cf->next, data, TRUE,
CF_CTRL_CONN_INFO_UPDATE, 0, NULL);
return result;
}
static bool time_to_start_h21(struct Curl_cfilter *cf,
struct Curl_easy *data,
struct curltime now)
{
struct cf_hc_ctx *ctx = cf->ctx;
timediff_t elapsed_ms;
if(!ctx->h21_baller.enabled || cf_hc_baller_has_started(&ctx->h21_baller))
return FALSE;
if(!ctx->h3_baller.enabled || !cf_hc_baller_is_active(&ctx->h3_baller))
return TRUE;
elapsed_ms = Curl_timediff(now, ctx->started);
if(elapsed_ms >= ctx->hard_eyeballs_timeout_ms) {
DEBUGF(LOG_CF(data, cf, "hard timeout of %dms reached, starting h21",
ctx->hard_eyeballs_timeout_ms));
return TRUE;
}
if(elapsed_ms >= ctx->soft_eyeballs_timeout_ms) {
if(cf_hc_baller_reply_ms(&ctx->h3_baller, data) < 0) {
DEBUGF(LOG_CF(data, cf, "soft timeout of %dms reached, h3 has not "
"seen any data, starting h21",
ctx->soft_eyeballs_timeout_ms));
return TRUE;
}
/* set the effective hard timeout again */
Curl_expire(data, ctx->hard_eyeballs_timeout_ms - elapsed_ms,
EXPIRE_ALPN_EYEBALLS);
}
return FALSE;
}
static CURLcode cf_hc_connect(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool blocking, bool *done)
{
struct cf_hc_ctx *ctx = cf->ctx;
struct curltime now;
CURLcode result = CURLE_OK;
(void)blocking;
if(cf->connected) {
*done = TRUE;
return CURLE_OK;
}
*done = FALSE;
now = Curl_now();
switch(ctx->state) {
case CF_HC_INIT:
DEBUGASSERT(!ctx->h3_baller.cf);
DEBUGASSERT(!ctx->h21_baller.cf);
DEBUGASSERT(!cf->next);
DEBUGF(LOG_CF(data, cf, "connect, init"));
ctx->started = now;
if(ctx->h3_baller.enabled) {
cf_hc_baller_init(&ctx->h3_baller, cf, data, "h3", TRNSPRT_QUIC);
if(ctx->h21_baller.enabled)
Curl_expire(data, ctx->soft_eyeballs_timeout_ms, EXPIRE_ALPN_EYEBALLS);
}
else if(ctx->h21_baller.enabled)
cf_hc_baller_init(&ctx->h21_baller, cf, data, "h21",
cf->conn->transport);
ctx->state = CF_HC_CONNECT;
/* FALLTHROUGH */
case CF_HC_CONNECT:
if(cf_hc_baller_is_active(&ctx->h3_baller)) {
result = cf_hc_baller_connect(&ctx->h3_baller, cf, data, done);
if(!result && *done) {
result = baller_connected(cf, data, &ctx->h3_baller);
goto out;
}
}
if(time_to_start_h21(cf, data, now)) {
cf_hc_baller_init(&ctx->h21_baller, cf, data, "h21",
cf->conn->transport);
}
if(cf_hc_baller_is_active(&ctx->h21_baller)) {
DEBUGF(LOG_CF(data, cf, "connect, check h21"));
result = cf_hc_baller_connect(&ctx->h21_baller, cf, data, done);
if(!result && *done) {
result = baller_connected(cf, data, &ctx->h21_baller);
goto out;
}
}
if((!ctx->h3_baller.enabled || ctx->h3_baller.result) &&
(!ctx->h21_baller.enabled || ctx->h21_baller.result)) {
/* both failed or disabled. we give up */
DEBUGF(LOG_CF(data, cf, "connect, all failed"));
result = ctx->result = ctx->h3_baller.enabled?
ctx->h3_baller.result : ctx->h21_baller.result;
ctx->state = CF_HC_FAILURE;
goto out;
}
result = CURLE_OK;
*done = FALSE;
break;
case CF_HC_FAILURE:
result = ctx->result;
cf->connected = FALSE;
*done = FALSE;
break;
case CF_HC_SUCCESS:
result = CURLE_OK;
cf->connected = TRUE;
*done = TRUE;
break;
}
out:
DEBUGF(LOG_CF(data, cf, "connect -> %d, done=%d", result, *done));
return result;
}
static int cf_hc_get_select_socks(struct Curl_cfilter *cf,
struct Curl_easy *data,
curl_socket_t *socks)
{
struct cf_hc_ctx *ctx = cf->ctx;
size_t i, j, s;
int brc, rc = GETSOCK_BLANK;
curl_socket_t bsocks[MAX_SOCKSPEREASYHANDLE];
struct cf_hc_baller *ballers[2];
if(cf->connected)
return cf->next->cft->get_select_socks(cf->next, data, socks);
ballers[0] = &ctx->h3_baller;
ballers[1] = &ctx->h21_baller;
for(i = s = 0; i < sizeof(ballers)/sizeof(ballers[0]); i++) {
struct cf_hc_baller *b = ballers[i];
if(!cf_hc_baller_is_active(b))
continue;
brc = Curl_conn_cf_get_select_socks(b->cf, data, bsocks);
DEBUGF(LOG_CF(data, cf, "get_selected_socks(%s) -> %x", b->name, brc));
if(!brc)
continue;
for(j = 0; j < MAX_SOCKSPEREASYHANDLE && s < MAX_SOCKSPEREASYHANDLE; ++j) {
if((brc & GETSOCK_WRITESOCK(j)) || (brc & GETSOCK_READSOCK(j))) {
socks[s] = bsocks[j];
if(brc & GETSOCK_WRITESOCK(j))
rc |= GETSOCK_WRITESOCK(s);
if(brc & GETSOCK_READSOCK(j))
rc |= GETSOCK_READSOCK(s);
s++;
}
}
}
DEBUGF(LOG_CF(data, cf, "get_selected_socks -> %x", rc));
return rc;
}
static bool cf_hc_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data)
{
struct cf_hc_ctx *ctx = cf->ctx;
if(cf->connected)
return cf->next->cft->has_data_pending(cf->next, data);
DEBUGF(LOG_CF((struct Curl_easy *)data, cf, "data_pending"));
return cf_hc_baller_data_pending(&ctx->h3_baller, data)
|| cf_hc_baller_data_pending(&ctx->h21_baller, data);
}
static struct curltime get_max_baller_time(struct Curl_cfilter *cf,
struct Curl_easy *data,
int query)
{
struct cf_hc_ctx *ctx = cf->ctx;
struct Curl_cfilter *cfb;
struct curltime t, tmax;
memset(&tmax, 0, sizeof(tmax));
memset(&t, 0, sizeof(t));
cfb = ctx->h21_baller.enabled? ctx->h21_baller.cf : NULL;
if(cfb && !cfb->cft->query(cfb, data, query, NULL, &t)) {
if((t.tv_sec || t.tv_usec) && Curl_timediff_us(t, tmax) > 0)
tmax = t;
}
memset(&t, 0, sizeof(t));
cfb = ctx->h3_baller.enabled? ctx->h3_baller.cf : NULL;
if(cfb && !cfb->cft->query(cfb, data, query, NULL, &t)) {
if((t.tv_sec || t.tv_usec) && Curl_timediff_us(t, tmax) > 0)
tmax = t;
}
return tmax;
}
static CURLcode cf_hc_query(struct Curl_cfilter *cf,
struct Curl_easy *data,
int query, int *pres1, void *pres2)
{
if(!cf->connected) {
switch(query) {
case CF_QUERY_TIMER_CONNECT: {
struct curltime *when = pres2;
*when = get_max_baller_time(cf, data, CF_QUERY_TIMER_CONNECT);
return CURLE_OK;
}
case CF_QUERY_TIMER_APPCONNECT: {
struct curltime *when = pres2;
*when = get_max_baller_time(cf, data, CF_QUERY_TIMER_APPCONNECT);
return CURLE_OK;
}
default:
break;
}
}
return cf->next?
cf->next->cft->query(cf->next, data, query, pres1, pres2) :
CURLE_UNKNOWN_OPTION;
}
static void cf_hc_close(struct Curl_cfilter *cf, struct Curl_easy *data)
{
DEBUGF(LOG_CF(data, cf, "close"));
cf_hc_reset(cf, data);
cf->connected = FALSE;
if(cf->next) {
cf->next->cft->close(cf->next, data);
Curl_conn_cf_discard_chain(&cf->next, data);
}
}
static void cf_hc_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct cf_hc_ctx *ctx = cf->ctx;
(void)data;
DEBUGF(LOG_CF(data, cf, "destroy"));
cf_hc_reset(cf, data);
Curl_safefree(ctx);
}
struct Curl_cftype Curl_cft_http_connect = {
"HTTPS-CONNECT",
0,
CURL_LOG_DEFAULT,
cf_hc_destroy,
cf_hc_connect,
cf_hc_close,
Curl_cf_def_get_host,
cf_hc_get_select_socks,
cf_hc_data_pending,
Curl_cf_def_send,
Curl_cf_def_recv,
Curl_cf_def_cntrl,
Curl_cf_def_conn_is_alive,
Curl_cf_def_conn_keep_alive,
cf_hc_query,
};
static CURLcode cf_hc_create(struct Curl_cfilter **pcf,
struct Curl_easy *data,
const struct Curl_dns_entry *remotehost,
bool try_h3, bool try_h21)
{
struct Curl_cfilter *cf = NULL;
struct cf_hc_ctx *ctx;
CURLcode result = CURLE_OK;
(void)data;
ctx = calloc(sizeof(*ctx), 1);
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
ctx->remotehost = remotehost;
ctx->h3_baller.enabled = try_h3;
ctx->h21_baller.enabled = try_h21;
result = Curl_cf_create(&cf, &Curl_cft_http_connect, ctx);
if(result)
goto out;
ctx = NULL;
cf_hc_reset(cf, data);
out:
*pcf = result? NULL : cf;
free(ctx);
return result;
}
CURLcode Curl_cf_http_connect_add(struct Curl_easy *data,
struct connectdata *conn,
int sockindex,
const struct Curl_dns_entry *remotehost,
bool try_h3, bool try_h21)
{
struct Curl_cfilter *cf;
CURLcode result = CURLE_OK;
DEBUGASSERT(data);
result = cf_hc_create(&cf, data, remotehost, try_h3, try_h21);
if(result)
goto out;
Curl_conn_cf_add(data, conn, sockindex, cf);
out:
return result;
}
CURLcode
Curl_cf_http_connect_insert_after(struct Curl_cfilter *cf_at,
struct Curl_easy *data,
const struct Curl_dns_entry *remotehost,
bool try_h3, bool try_h21)
{
struct Curl_cfilter *cf;
CURLcode result;
DEBUGASSERT(data);
result = cf_hc_create(&cf, data, remotehost, try_h3, try_h21);
if(result)
goto out;
Curl_conn_cf_insert_after(cf_at, cf);
out:
return result;
}
CURLcode Curl_cf_https_setup(struct Curl_easy *data,
struct connectdata *conn,
int sockindex,
const struct Curl_dns_entry *remotehost)
{
bool try_h3 = FALSE, try_h21 = TRUE; /* defaults, for now */
CURLcode result = CURLE_OK;
(void)sockindex;
(void)remotehost;
if(!conn->bits.tls_enable_alpn)
goto out;
if(data->state.httpwant == CURL_HTTP_VERSION_3ONLY) {
result = Curl_conn_may_http3(data, conn);
if(result) /* can't do it */
goto out;
try_h3 = TRUE;
try_h21 = FALSE;
}
else if(data->state.httpwant >= CURL_HTTP_VERSION_3) {
/* We assume that silently not even trying H3 is ok here */
/* TODO: should we fail instead? */
try_h3 = (Curl_conn_may_http3(data, conn) == CURLE_OK);
try_h21 = TRUE;
}
result = Curl_cf_http_connect_add(data, conn, sockindex, remotehost,
try_h3, try_h21);
out:
return result;
}
#endif /* !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER) */

View file

@ -0,0 +1,58 @@
#ifndef HEADER_CURL_CF_HTTP_H
#define HEADER_CURL_CF_HTTP_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#if !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER)
struct Curl_cfilter;
struct Curl_easy;
struct connectdata;
struct Curl_cftype;
struct Curl_dns_entry;
extern struct Curl_cftype Curl_cft_http_connect;
CURLcode Curl_cf_http_connect_add(struct Curl_easy *data,
struct connectdata *conn,
int sockindex,
const struct Curl_dns_entry *remotehost,
bool try_h3, bool try_h21);
CURLcode
Curl_cf_http_connect_insert_after(struct Curl_cfilter *cf_at,
struct Curl_easy *data,
const struct Curl_dns_entry *remotehost,
bool try_h3, bool try_h21);
CURLcode Curl_cf_https_setup(struct Curl_easy *data,
struct connectdata *conn,
int sockindex,
const struct Curl_dns_entry *remotehost);
#endif /* !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER) */
#endif /* HEADER_CURL_CF_HTTP_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,185 @@
#ifndef HEADER_CURL_CF_SOCKET_H
#define HEADER_CURL_CF_SOCKET_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#include "nonblock.h" /* for curlx_nonblock(), formerly Curl_nonblock() */
#include "sockaddr.h"
struct Curl_addrinfo;
struct Curl_cfilter;
struct Curl_easy;
struct connectdata;
struct Curl_sockaddr_ex;
/*
* The Curl_sockaddr_ex structure is basically libcurl's external API
* curl_sockaddr structure with enough space available to directly hold any
* protocol-specific address structures. The variable declared here will be
* used to pass / receive data to/from the fopensocket callback if this has
* been set, before that, it is initialized from parameters.
*/
struct Curl_sockaddr_ex {
int family;
int socktype;
int protocol;
unsigned int addrlen;
union {
struct sockaddr addr;
struct Curl_sockaddr_storage buff;
} _sa_ex_u;
};
#define sa_addr _sa_ex_u.addr
/*
* Create a socket based on info from 'conn' and 'ai'.
*
* Fill in 'addr' and 'sockfd' accordingly if OK is returned. If the open
* socket callback is set, used that!
*
*/
CURLcode Curl_socket_open(struct Curl_easy *data,
const struct Curl_addrinfo *ai,
struct Curl_sockaddr_ex *addr,
int transport,
curl_socket_t *sockfd);
int Curl_socket_close(struct Curl_easy *data, struct connectdata *conn,
curl_socket_t sock);
/**
* Determine the curl code for a socket connect() == -1 with errno.
*/
CURLcode Curl_socket_connect_result(struct Curl_easy *data,
const char *ipaddress, int error);
#ifdef USE_WINSOCK
/* When you run a program that uses the Windows Sockets API, you may
experience slow performance when you copy data to a TCP server.
https://support.microsoft.com/kb/823764
Work-around: Make the Socket Send Buffer Size Larger Than the Program Send
Buffer Size
*/
void Curl_sndbufset(curl_socket_t sockfd);
#else
#define Curl_sndbufset(y) Curl_nop_stmt
#endif
/**
* Assign the address `ai` to the Curl_sockaddr_ex `dest` and
* set the transport used.
*/
void Curl_sock_assign_addr(struct Curl_sockaddr_ex *dest,
const struct Curl_addrinfo *ai,
int transport);
/**
* Creates a cfilter that opens a TCP socket to the given address
* when calling its `connect` implementation.
* The filter will not touch any connection/data flags and can be
* used in happy eyeballing. Once selected for use, its `_active()`
* method needs to be called.
*/
CURLcode Curl_cf_tcp_create(struct Curl_cfilter **pcf,
struct Curl_easy *data,
struct connectdata *conn,
const struct Curl_addrinfo *ai,
int transport);
/**
* Creates a cfilter that opens a UDP socket to the given address
* when calling its `connect` implementation.
* The filter will not touch any connection/data flags and can be
* used in happy eyeballing. Once selected for use, its `_active()`
* method needs to be called.
*/
CURLcode Curl_cf_udp_create(struct Curl_cfilter **pcf,
struct Curl_easy *data,
struct connectdata *conn,
const struct Curl_addrinfo *ai,
int transport);
/**
* Creates a cfilter that opens a UNIX socket to the given address
* when calling its `connect` implementation.
* The filter will not touch any connection/data flags and can be
* used in happy eyeballing. Once selected for use, its `_active()`
* method needs to be called.
*/
CURLcode Curl_cf_unix_create(struct Curl_cfilter **pcf,
struct Curl_easy *data,
struct connectdata *conn,
const struct Curl_addrinfo *ai,
int transport);
/**
* Creates a cfilter that keeps a listening socket.
*/
CURLcode Curl_conn_tcp_listen_set(struct Curl_easy *data,
struct connectdata *conn,
int sockindex,
curl_socket_t *s);
/**
* Replace the listen socket with the accept()ed one.
*/
CURLcode Curl_conn_tcp_accepted_set(struct Curl_easy *data,
struct connectdata *conn,
int sockindex,
curl_socket_t *s);
/**
* Return TRUE iff `cf` is a socket filter.
*/
bool Curl_cf_is_socket(struct Curl_cfilter *cf);
/**
* Peek at the socket and remote ip/port the socket filter is using.
* The filter owns all returned values.
* @param psock pointer to hold socket descriptor or NULL
* @param paddr pointer to hold addr reference or NULL
* @param pr_ip_str pointer to hold remote addr as string or NULL
* @param pr_port pointer to hold remote port number or NULL
* @param pl_ip_str pointer to hold local addr as string or NULL
* @param pl_port pointer to hold local port number or NULL
* Returns error if the filter is of invalid type.
*/
CURLcode Curl_cf_socket_peek(struct Curl_cfilter *cf,
struct Curl_easy *data,
curl_socket_t *psock,
const struct Curl_sockaddr_ex **paddr,
const char **pr_ip_str, int *pr_port,
const char **pl_ip_str, int *pl_port);
extern struct Curl_cftype Curl_cft_tcp;
extern struct Curl_cftype Curl_cft_udp;
extern struct Curl_cftype Curl_cft_unix;
extern struct Curl_cftype Curl_cft_tcp_accept;
#endif /* HEADER_CURL_CF_SOCKET_H */

View file

@ -0,0 +1,663 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#include "urldata.h"
#include "strerror.h"
#include "cfilters.h"
#include "connect.h"
#include "url.h" /* for Curl_safefree() */
#include "sendf.h"
#include "sockaddr.h" /* required for Curl_sockaddr_storage */
#include "multiif.h"
#include "progress.h"
#include "warnless.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
#ifndef ARRAYSIZE
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
#endif
void Curl_cf_def_destroy_this(struct Curl_cfilter *cf, struct Curl_easy *data)
{
(void)cf;
(void)data;
}
void Curl_cf_def_close(struct Curl_cfilter *cf, struct Curl_easy *data)
{
cf->connected = FALSE;
if(cf->next)
cf->next->cft->close(cf->next, data);
}
CURLcode Curl_cf_def_connect(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool blocking, bool *done)
{
CURLcode result;
if(cf->connected) {
*done = TRUE;
return CURLE_OK;
}
if(cf->next) {
result = cf->next->cft->connect(cf->next, data, blocking, done);
if(!result && *done) {
cf->connected = TRUE;
}
return result;
}
*done = FALSE;
return CURLE_FAILED_INIT;
}
void Curl_cf_def_get_host(struct Curl_cfilter *cf, struct Curl_easy *data,
const char **phost, const char **pdisplay_host,
int *pport)
{
if(cf->next)
cf->next->cft->get_host(cf->next, data, phost, pdisplay_host, pport);
else {
*phost = cf->conn->host.name;
*pdisplay_host = cf->conn->host.dispname;
*pport = cf->conn->port;
}
}
int Curl_cf_def_get_select_socks(struct Curl_cfilter *cf,
struct Curl_easy *data,
curl_socket_t *socks)
{
return cf->next?
cf->next->cft->get_select_socks(cf->next, data, socks) : 0;
}
bool Curl_cf_def_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data)
{
return cf->next?
cf->next->cft->has_data_pending(cf->next, data) : FALSE;
}
ssize_t Curl_cf_def_send(struct Curl_cfilter *cf, struct Curl_easy *data,
const void *buf, size_t len, CURLcode *err)
{
return cf->next?
cf->next->cft->do_send(cf->next, data, buf, len, err) :
CURLE_RECV_ERROR;
}
ssize_t Curl_cf_def_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
char *buf, size_t len, CURLcode *err)
{
return cf->next?
cf->next->cft->do_recv(cf->next, data, buf, len, err) :
CURLE_SEND_ERROR;
}
bool Curl_cf_def_conn_is_alive(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool *input_pending)
{
return cf->next?
cf->next->cft->is_alive(cf->next, data, input_pending) :
FALSE; /* pessimistic in absence of data */
}
CURLcode Curl_cf_def_conn_keep_alive(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
return cf->next?
cf->next->cft->keep_alive(cf->next, data) :
CURLE_OK;
}
CURLcode Curl_cf_def_query(struct Curl_cfilter *cf,
struct Curl_easy *data,
int query, int *pres1, void *pres2)
{
return cf->next?
cf->next->cft->query(cf->next, data, query, pres1, pres2) :
CURLE_UNKNOWN_OPTION;
}
void Curl_conn_cf_discard_chain(struct Curl_cfilter **pcf,
struct Curl_easy *data)
{
struct Curl_cfilter *cfn, *cf = *pcf;
if(cf) {
*pcf = NULL;
while(cf) {
cfn = cf->next;
/* prevent destroying filter to mess with its sub-chain, since
* we have the reference now and will call destroy on it.
*/
cf->next = NULL;
cf->cft->destroy(cf, data);
free(cf);
cf = cfn;
}
}
}
void Curl_conn_cf_discard_all(struct Curl_easy *data,
struct connectdata *conn, int index)
{
Curl_conn_cf_discard_chain(&conn->cfilter[index], data);
}
void Curl_conn_close(struct Curl_easy *data, int index)
{
struct Curl_cfilter *cf;
DEBUGASSERT(data->conn);
/* it is valid to call that without filters being present */
cf = data->conn->cfilter[index];
if(cf) {
cf->cft->close(cf, data);
}
}
ssize_t Curl_conn_recv(struct Curl_easy *data, int num, char *buf,
size_t len, CURLcode *code)
{
struct Curl_cfilter *cf;
DEBUGASSERT(data);
DEBUGASSERT(data->conn);
cf = data->conn->cfilter[num];
while(cf && !cf->connected) {
cf = cf->next;
}
if(cf) {
return cf->cft->do_recv(cf, data, buf, len, code);
}
failf(data, CMSGI(data->conn, num, "recv: no filter connected"));
*code = CURLE_FAILED_INIT;
return -1;
}
ssize_t Curl_conn_send(struct Curl_easy *data, int num,
const void *mem, size_t len, CURLcode *code)
{
struct Curl_cfilter *cf;
DEBUGASSERT(data);
DEBUGASSERT(data->conn);
cf = data->conn->cfilter[num];
while(cf && !cf->connected) {
cf = cf->next;
}
if(cf) {
return cf->cft->do_send(cf, data, mem, len, code);
}
failf(data, CMSGI(data->conn, num, "send: no filter connected"));
DEBUGASSERT(0);
*code = CURLE_FAILED_INIT;
return -1;
}
CURLcode Curl_cf_create(struct Curl_cfilter **pcf,
const struct Curl_cftype *cft,
void *ctx)
{
struct Curl_cfilter *cf;
CURLcode result = CURLE_OUT_OF_MEMORY;
DEBUGASSERT(cft);
cf = calloc(sizeof(*cf), 1);
if(!cf)
goto out;
cf->cft = cft;
cf->ctx = ctx;
result = CURLE_OK;
out:
*pcf = cf;
return result;
}
void Curl_conn_cf_add(struct Curl_easy *data,
struct connectdata *conn,
int index,
struct Curl_cfilter *cf)
{
(void)data;
DEBUGASSERT(conn);
DEBUGASSERT(!cf->conn);
DEBUGASSERT(!cf->next);
cf->next = conn->cfilter[index];
cf->conn = conn;
cf->sockindex = index;
conn->cfilter[index] = cf;
DEBUGF(LOG_CF(data, cf, "added"));
}
void Curl_conn_cf_insert_after(struct Curl_cfilter *cf_at,
struct Curl_cfilter *cf_new)
{
struct Curl_cfilter *tail, **pnext;
DEBUGASSERT(cf_at);
DEBUGASSERT(cf_new);
DEBUGASSERT(!cf_new->conn);
tail = cf_at->next;
cf_at->next = cf_new;
do {
cf_new->conn = cf_at->conn;
cf_new->sockindex = cf_at->sockindex;
pnext = &cf_new->next;
cf_new = cf_new->next;
} while(cf_new);
*pnext = tail;
}
void Curl_conn_cf_discard(struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct Curl_cfilter **pprev = &cf->conn->cfilter[cf->sockindex];
/* remove from chain if still in there */
DEBUGASSERT(cf);
while (*pprev) {
if (*pprev == cf) {
*pprev = cf->next;
break;
}
pprev = &((*pprev)->next);
}
cf->cft->destroy(cf, data);
free(cf);
}
CURLcode Curl_conn_cf_connect(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool blocking, bool *done)
{
if(cf)
return cf->cft->connect(cf, data, blocking, done);
return CURLE_FAILED_INIT;
}
void Curl_conn_cf_close(struct Curl_cfilter *cf, struct Curl_easy *data)
{
if(cf)
cf->cft->close(cf, data);
}
int Curl_conn_cf_get_select_socks(struct Curl_cfilter *cf,
struct Curl_easy *data,
curl_socket_t *socks)
{
if(cf)
return cf->cft->get_select_socks(cf, data, socks);
return 0;
}
bool Curl_conn_cf_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data)
{
if(cf)
return cf->cft->has_data_pending(cf, data);
return FALSE;
}
ssize_t Curl_conn_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data,
const void *buf, size_t len, CURLcode *err)
{
if(cf)
return cf->cft->do_send(cf, data, buf, len, err);
*err = CURLE_SEND_ERROR;
return -1;
}
ssize_t Curl_conn_cf_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
char *buf, size_t len, CURLcode *err)
{
if(cf)
return cf->cft->do_recv(cf, data, buf, len, err);
*err = CURLE_RECV_ERROR;
return -1;
}
CURLcode Curl_conn_connect(struct Curl_easy *data,
int sockindex,
bool blocking,
bool *done)
{
struct Curl_cfilter *cf;
CURLcode result = CURLE_OK;
DEBUGASSERT(data);
DEBUGASSERT(data->conn);
cf = data->conn->cfilter[sockindex];
DEBUGASSERT(cf);
if(!cf)
return CURLE_FAILED_INIT;
*done = cf->connected;
if(!*done) {
result = cf->cft->connect(cf, data, blocking, done);
if(!result && *done) {
Curl_conn_ev_update_info(data, data->conn);
Curl_conn_report_connect_stats(data, data->conn);
data->conn->keepalive = Curl_now();
}
else if(result) {
Curl_conn_report_connect_stats(data, data->conn);
}
}
return result;
}
bool Curl_conn_is_connected(struct connectdata *conn, int sockindex)
{
struct Curl_cfilter *cf;
cf = conn->cfilter[sockindex];
return cf && cf->connected;
}
bool Curl_conn_is_ip_connected(struct Curl_easy *data, int sockindex)
{
struct Curl_cfilter *cf;
cf = data->conn->cfilter[sockindex];
while(cf) {
if(cf->connected)
return TRUE;
if(cf->cft->flags & CF_TYPE_IP_CONNECT)
return FALSE;
cf = cf->next;
}
return FALSE;
}
bool Curl_conn_is_ssl(struct connectdata *conn, int sockindex)
{
struct Curl_cfilter *cf = conn? conn->cfilter[sockindex] : NULL;
for(; cf; cf = cf->next) {
if(cf->cft->flags & CF_TYPE_SSL)
return TRUE;
if(cf->cft->flags & CF_TYPE_IP_CONNECT)
return FALSE;
}
return FALSE;
}
bool Curl_conn_is_multiplex(struct connectdata *conn, int sockindex)
{
struct Curl_cfilter *cf = conn? conn->cfilter[sockindex] : NULL;
for(; cf; cf = cf->next) {
if(cf->cft->flags & CF_TYPE_MULTIPLEX)
return TRUE;
if(cf->cft->flags & CF_TYPE_IP_CONNECT
|| cf->cft->flags & CF_TYPE_SSL)
return FALSE;
}
return FALSE;
}
bool Curl_conn_data_pending(struct Curl_easy *data, int sockindex)
{
struct Curl_cfilter *cf;
(void)data;
DEBUGASSERT(data);
DEBUGASSERT(data->conn);
cf = data->conn->cfilter[sockindex];
while(cf && !cf->connected) {
cf = cf->next;
}
if(cf) {
return cf->cft->has_data_pending(cf, data);
}
return FALSE;
}
int Curl_conn_get_select_socks(struct Curl_easy *data, int sockindex,
curl_socket_t *socks)
{
struct Curl_cfilter *cf;
DEBUGASSERT(data);
DEBUGASSERT(data->conn);
cf = data->conn->cfilter[sockindex];
/* if the next one is not yet connected, that's the one we want */
while(cf && cf->next && !cf->next->connected)
cf = cf->next;
if(cf) {
return cf->cft->get_select_socks(cf, data, socks);
}
return GETSOCK_BLANK;
}
void Curl_conn_get_host(struct Curl_easy *data, int sockindex,
const char **phost, const char **pdisplay_host,
int *pport)
{
struct Curl_cfilter *cf;
DEBUGASSERT(data->conn);
cf = data->conn->cfilter[sockindex];
if(cf) {
cf->cft->get_host(cf, data, phost, pdisplay_host, pport);
}
else {
/* Some filter ask during shutdown for this, mainly for debugging
* purposes. We hand out the defaults, however this is not always
* accurate, as the connection might be tunneled, etc. But all that
* state is already gone here. */
*phost = data->conn->host.name;
*pdisplay_host = data->conn->host.dispname;
*pport = data->conn->remote_port;
}
}
CURLcode Curl_cf_def_cntrl(struct Curl_cfilter *cf,
struct Curl_easy *data,
int event, int arg1, void *arg2)
{
(void)cf;
(void)data;
(void)event;
(void)arg1;
(void)arg2;
return CURLE_OK;
}
CURLcode Curl_conn_cf_cntrl(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool ignore_result,
int event, int arg1, void *arg2)
{
CURLcode result = CURLE_OK;
for(; cf; cf = cf->next) {
if(Curl_cf_def_cntrl == cf->cft->cntrl)
continue;
result = cf->cft->cntrl(cf, data, event, arg1, arg2);
if(!ignore_result && result)
break;
}
return result;
}
curl_socket_t Curl_conn_cf_get_socket(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
curl_socket_t sock;
if(cf && !cf->cft->query(cf, data, CF_QUERY_SOCKET, NULL, &sock))
return sock;
return CURL_SOCKET_BAD;
}
curl_socket_t Curl_conn_get_socket(struct Curl_easy *data, int sockindex)
{
struct Curl_cfilter *cf;
cf = data->conn? data->conn->cfilter[sockindex] : NULL;
/* if the top filter has not connected, ask it (and its sub-filters)
* for the socket. Otherwise conn->sock[sockindex] should have it.
*/
if(cf && !cf->connected)
return Curl_conn_cf_get_socket(cf, data);
return data->conn? data->conn->sock[sockindex] : CURL_SOCKET_BAD;
}
static CURLcode cf_cntrl_all(struct connectdata *conn,
struct Curl_easy *data,
bool ignore_result,
int event, int arg1, void *arg2)
{
CURLcode result = CURLE_OK;
size_t i;
for(i = 0; i < ARRAYSIZE(conn->cfilter); ++i) {
result = Curl_conn_cf_cntrl(conn->cfilter[i], data, ignore_result,
event, arg1, arg2);
if(!ignore_result && result)
break;
}
return result;
}
void Curl_conn_ev_data_attach(struct connectdata *conn,
struct Curl_easy *data)
{
cf_cntrl_all(conn, data, TRUE, CF_CTRL_DATA_ATTACH, 0, NULL);
}
void Curl_conn_ev_data_detach(struct connectdata *conn,
struct Curl_easy *data)
{
cf_cntrl_all(conn, data, TRUE, CF_CTRL_DATA_DETACH, 0, NULL);
}
CURLcode Curl_conn_ev_data_setup(struct Curl_easy *data)
{
return cf_cntrl_all(data->conn, data, FALSE,
CF_CTRL_DATA_SETUP, 0, NULL);
}
CURLcode Curl_conn_ev_data_idle(struct Curl_easy *data)
{
return cf_cntrl_all(data->conn, data, FALSE,
CF_CTRL_DATA_IDLE, 0, NULL);
}
/**
* Notify connection filters that the transfer represented by `data`
* is donw with sending data (e.g. has uploaded everything).
*/
void Curl_conn_ev_data_done_send(struct Curl_easy *data)
{
cf_cntrl_all(data->conn, data, TRUE, CF_CTRL_DATA_DONE_SEND, 0, NULL);
}
/**
* Notify connection filters that the transfer represented by `data`
* is finished - eventually premature, e.g. before being complete.
*/
void Curl_conn_ev_data_done(struct Curl_easy *data, bool premature)
{
cf_cntrl_all(data->conn, data, TRUE, CF_CTRL_DATA_DONE, premature, NULL);
}
CURLcode Curl_conn_ev_data_pause(struct Curl_easy *data, bool do_pause)
{
return cf_cntrl_all(data->conn, data, FALSE,
CF_CTRL_DATA_PAUSE, do_pause, NULL);
}
void Curl_conn_ev_update_info(struct Curl_easy *data,
struct connectdata *conn)
{
cf_cntrl_all(conn, data, TRUE, CF_CTRL_CONN_INFO_UPDATE, 0, NULL);
}
void Curl_conn_report_connect_stats(struct Curl_easy *data,
struct connectdata *conn)
{
struct Curl_cfilter *cf = conn->cfilter[FIRSTSOCKET];
if(cf) {
struct curltime connected;
struct curltime appconnected;
memset(&connected, 0, sizeof(connected));
cf->cft->query(cf, data, CF_QUERY_TIMER_CONNECT, NULL, &connected);
if(connected.tv_sec || connected.tv_usec)
Curl_pgrsTimeWas(data, TIMER_CONNECT, connected);
memset(&appconnected, 0, sizeof(appconnected));
cf->cft->query(cf, data, CF_QUERY_TIMER_APPCONNECT, NULL, &appconnected);
if(appconnected.tv_sec || appconnected.tv_usec)
Curl_pgrsTimeWas(data, TIMER_APPCONNECT, appconnected);
}
}
bool Curl_conn_is_alive(struct Curl_easy *data, struct connectdata *conn,
bool *input_pending)
{
struct Curl_cfilter *cf = conn->cfilter[FIRSTSOCKET];
return cf && !cf->conn->bits.close &&
cf->cft->is_alive(cf, data, input_pending);
}
CURLcode Curl_conn_keep_alive(struct Curl_easy *data,
struct connectdata *conn,
int sockindex)
{
struct Curl_cfilter *cf = conn->cfilter[sockindex];
return cf? cf->cft->keep_alive(cf, data) : CURLE_OK;
}
size_t Curl_conn_get_max_concurrent(struct Curl_easy *data,
struct connectdata *conn,
int sockindex)
{
CURLcode result;
int n = 0;
struct Curl_cfilter *cf = conn->cfilter[sockindex];
result = cf? cf->cft->query(cf, data, CF_QUERY_MAX_CONCURRENT,
&n, NULL) : CURLE_UNKNOWN_OPTION;
return (result || n <= 0)? 1 : (size_t)n;
}

View file

@ -0,0 +1,539 @@
#ifndef HEADER_CURL_CFILTERS_H
#define HEADER_CURL_CFILTERS_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
struct Curl_cfilter;
struct Curl_easy;
struct Curl_dns_entry;
struct connectdata;
/* Callback to destroy resources held by this filter instance.
* Implementations MUST NOT chain calls to cf->next.
*/
typedef void Curl_cft_destroy_this(struct Curl_cfilter *cf,
struct Curl_easy *data);
typedef void Curl_cft_close(struct Curl_cfilter *cf,
struct Curl_easy *data);
typedef CURLcode Curl_cft_connect(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool blocking, bool *done);
/* Return the hostname and port the connection goes to.
* This may change with the connection state of filters when tunneling
* is involved.
* @param cf the filter to ask
* @param data the easy handle currently active
* @param phost on return, points to the relevant, real hostname.
* this is owned by the connection.
* @param pdisplay_host on return, points to the printable hostname.
* this is owned by the connection.
* @param pport on return, contains the port number
*/
typedef void Curl_cft_get_host(struct Curl_cfilter *cf,
struct Curl_easy *data,
const char **phost,
const char **pdisplay_host,
int *pport);
/* Filters may return sockets and fdset flags they are waiting for.
* The passes array has room for up to MAX_SOCKSPEREASYHANDLE sockets.
* @return read/write fdset for index in socks
* or GETSOCK_BLANK when nothing to wait on
*/
typedef int Curl_cft_get_select_socks(struct Curl_cfilter *cf,
struct Curl_easy *data,
curl_socket_t *socks);
typedef bool Curl_cft_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data);
typedef ssize_t Curl_cft_send(struct Curl_cfilter *cf,
struct Curl_easy *data, /* transfer */
const void *buf, /* data to write */
size_t len, /* amount to write */
CURLcode *err); /* error to return */
typedef ssize_t Curl_cft_recv(struct Curl_cfilter *cf,
struct Curl_easy *data, /* transfer */
char *buf, /* store data here */
size_t len, /* amount to read */
CURLcode *err); /* error to return */
typedef bool Curl_cft_conn_is_alive(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool *input_pending);
typedef CURLcode Curl_cft_conn_keep_alive(struct Curl_cfilter *cf,
struct Curl_easy *data);
/**
* Events/controls for connection filters, their arguments and
* return code handling. Filter callbacks are invoked "top down".
* Return code handling:
* "first fail" meaning that the first filter returning != CURLE_OK, will
* abort further event distribution and determine the result.
* "ignored" meaning return values are ignored and the event is distributed
* to all filters in the chain. Overall result is always CURLE_OK.
*/
/* data event arg1 arg2 return */
#define CF_CTRL_DATA_ATTACH 1 /* 0 NULL ignored */
#define CF_CTRL_DATA_DETACH 2 /* 0 NULL ignored */
#define CF_CTRL_DATA_SETUP 4 /* 0 NULL first fail */
#define CF_CTRL_DATA_IDLE 5 /* 0 NULL first fail */
#define CF_CTRL_DATA_PAUSE 6 /* on/off NULL first fail */
#define CF_CTRL_DATA_DONE 7 /* premature NULL ignored */
#define CF_CTRL_DATA_DONE_SEND 8 /* 0 NULL ignored */
/* update conn info at connection and data */
#define CF_CTRL_CONN_INFO_UPDATE (256+0) /* 0 NULL ignored */
/**
* Handle event/control for the filter.
* Implementations MUST NOT chain calls to cf->next.
*/
typedef CURLcode Curl_cft_cntrl(struct Curl_cfilter *cf,
struct Curl_easy *data,
int event, int arg1, void *arg2);
/**
* Queries to ask via a `Curl_cft_query *query` method on a cfilter chain.
* - MAX_CONCURRENT: the maximum number of parallel transfers the filter
* chain expects to handle at the same time.
* default: 1 if no filter overrides.
* - CONNECT_REPLY_MS: milliseconds until the first indication of a server
* response was received on a connect. For TCP, this
* reflects the time until the socket connected. On UDP
* this gives the time the first bytes from the server
* were received.
* -1 if not determined yet.
* - CF_QUERY_SOCKET: the socket used by the filter chain
*/
/* query res1 res2 */
#define CF_QUERY_MAX_CONCURRENT 1 /* number - */
#define CF_QUERY_CONNECT_REPLY_MS 2 /* number - */
#define CF_QUERY_SOCKET 3 /* - curl_socket_t */
#define CF_QUERY_TIMER_CONNECT 4 /* - struct curltime */
#define CF_QUERY_TIMER_APPCONNECT 5 /* - struct curltime */
/**
* Query the cfilter for properties. Filters ignorant of a query will
* pass it "down" the filter chain.
*/
typedef CURLcode Curl_cft_query(struct Curl_cfilter *cf,
struct Curl_easy *data,
int query, int *pres1, void *pres2);
/**
* Type flags for connection filters. A filter can have none, one or
* many of those. Use to evaluate state/capabilities of a filter chain.
*
* CF_TYPE_IP_CONNECT: provides an IP connection or sth equivalent, like
* a CONNECT tunnel, a UNIX domain socket, a QUIC
* connection, etc.
* CF_TYPE_SSL: provide SSL/TLS
* CF_TYPE_MULTIPLEX: provides multiplexing of easy handles
*/
#define CF_TYPE_IP_CONNECT (1 << 0)
#define CF_TYPE_SSL (1 << 1)
#define CF_TYPE_MULTIPLEX (1 << 2)
/* A connection filter type, e.g. specific implementation. */
struct Curl_cftype {
const char *name; /* name of the filter type */
int flags; /* flags of filter type */
int log_level; /* log level for such filters */
Curl_cft_destroy_this *destroy; /* destroy resources of this cf */
Curl_cft_connect *connect; /* establish connection */
Curl_cft_close *close; /* close conn */
Curl_cft_get_host *get_host; /* host filter talks to */
Curl_cft_get_select_socks *get_select_socks;/* sockets to select on */
Curl_cft_data_pending *has_data_pending;/* conn has data pending */
Curl_cft_send *do_send; /* send data */
Curl_cft_recv *do_recv; /* receive data */
Curl_cft_cntrl *cntrl; /* events/control */
Curl_cft_conn_is_alive *is_alive; /* FALSE if conn is dead, Jim! */
Curl_cft_conn_keep_alive *keep_alive; /* try to keep it alive */
Curl_cft_query *query; /* query filter chain */
};
/* A connection filter instance, e.g. registered at a connection */
struct Curl_cfilter {
const struct Curl_cftype *cft; /* the type providing implementation */
struct Curl_cfilter *next; /* next filter in chain */
void *ctx; /* filter type specific settings */
struct connectdata *conn; /* the connection this filter belongs to */
int sockindex; /* the index the filter is installed at */
BIT(connected); /* != 0 iff this filter is connected */
};
/* Default implementations for the type functions, implementing nop. */
void Curl_cf_def_destroy_this(struct Curl_cfilter *cf,
struct Curl_easy *data);
/* Default implementations for the type functions, implementing pass-through
* the filter chain. */
void Curl_cf_def_close(struct Curl_cfilter *cf, struct Curl_easy *data);
CURLcode Curl_cf_def_connect(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool blocking, bool *done);
void Curl_cf_def_get_host(struct Curl_cfilter *cf, struct Curl_easy *data,
const char **phost, const char **pdisplay_host,
int *pport);
int Curl_cf_def_get_select_socks(struct Curl_cfilter *cf,
struct Curl_easy *data,
curl_socket_t *socks);
bool Curl_cf_def_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data);
ssize_t Curl_cf_def_send(struct Curl_cfilter *cf, struct Curl_easy *data,
const void *buf, size_t len, CURLcode *err);
ssize_t Curl_cf_def_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
char *buf, size_t len, CURLcode *err);
CURLcode Curl_cf_def_cntrl(struct Curl_cfilter *cf,
struct Curl_easy *data,
int event, int arg1, void *arg2);
bool Curl_cf_def_conn_is_alive(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool *input_pending);
CURLcode Curl_cf_def_conn_keep_alive(struct Curl_cfilter *cf,
struct Curl_easy *data);
CURLcode Curl_cf_def_query(struct Curl_cfilter *cf,
struct Curl_easy *data,
int query, int *pres1, void *pres2);
/**
* Create a new filter instance, unattached to the filter chain.
* Use Curl_conn_cf_add() to add it to the chain.
* @param pcf on success holds the created instance
* @param cft the filter type
* @param ctx the type specific context to use
*/
CURLcode Curl_cf_create(struct Curl_cfilter **pcf,
const struct Curl_cftype *cft,
void *ctx);
/**
* Add a filter instance to the `sockindex` filter chain at connection
* `conn`. The filter must not already be attached. It is inserted at
* the start of the chain (top).
*/
void Curl_conn_cf_add(struct Curl_easy *data,
struct connectdata *conn,
int sockindex,
struct Curl_cfilter *cf);
/**
* Insert a filter (chain) after `cf_at`.
* `cf_new` must not already be attached.
*/
void Curl_conn_cf_insert_after(struct Curl_cfilter *cf_at,
struct Curl_cfilter *cf_new);
/**
* Discard, e.g. remove and destroy a specific filter instance.
* If the filter is attached to a connection, it will be removed before
* it is destroyed.
*/
void Curl_conn_cf_discard(struct Curl_cfilter *cf, struct Curl_easy *data);
/**
* Discard all cfilters starting with `*pcf` and clearing it afterwards.
*/
void Curl_conn_cf_discard_chain(struct Curl_cfilter **pcf,
struct Curl_easy *data);
/**
* Remove and destroy all filters at chain `sockindex` on connection `conn`.
*/
void Curl_conn_cf_discard_all(struct Curl_easy *data,
struct connectdata *conn,
int sockindex);
CURLcode Curl_conn_cf_connect(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool blocking, bool *done);
void Curl_conn_cf_close(struct Curl_cfilter *cf, struct Curl_easy *data);
int Curl_conn_cf_get_select_socks(struct Curl_cfilter *cf,
struct Curl_easy *data,
curl_socket_t *socks);
bool Curl_conn_cf_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data);
ssize_t Curl_conn_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data,
const void *buf, size_t len, CURLcode *err);
ssize_t Curl_conn_cf_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
char *buf, size_t len, CURLcode *err);
CURLcode Curl_conn_cf_cntrl(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool ignore_result,
int event, int arg1, void *arg2);
/**
* Get the socket used by the filter chain starting at `cf`.
* Returns CURL_SOCKET_BAD if not available.
*/
curl_socket_t Curl_conn_cf_get_socket(struct Curl_cfilter *cf,
struct Curl_easy *data);
#define CURL_CF_SSL_DEFAULT -1
#define CURL_CF_SSL_DISABLE 0
#define CURL_CF_SSL_ENABLE 1
/**
* Bring the filter chain at `sockindex` for connection `data->conn` into
* connected state. Which will set `*done` to TRUE.
* This can be called on an already connected chain with no side effects.
* When not `blocking`, calls may return without error and `*done != TRUE`,
* while the individual filters negotiated the connection.
*/
CURLcode Curl_conn_connect(struct Curl_easy *data, int sockindex,
bool blocking, bool *done);
/**
* Check if the filter chain at `sockindex` for connection `conn` is
* completely connected.
*/
bool Curl_conn_is_connected(struct connectdata *conn, int sockindex);
/**
* Determine if we have reached the remote host on IP level, e.g.
* have a TCP connection. This turns TRUE before a possible SSL
* handshake has been started/done.
*/
bool Curl_conn_is_ip_connected(struct Curl_easy *data, int sockindex);
/**
* Determine if the connection is using SSL to the remote host
* (or will be once connected). This will return FALSE, if SSL
* is only used in proxying and not for the tunnel itself.
*/
bool Curl_conn_is_ssl(struct connectdata *conn, int sockindex);
/**
* Connection provides multiplexing of easy handles at `socketindex`.
*/
bool Curl_conn_is_multiplex(struct connectdata *conn, int sockindex);
/**
* Close the filter chain at `sockindex` for connection `data->conn`.
* Filters remain in place and may be connected again afterwards.
*/
void Curl_conn_close(struct Curl_easy *data, int sockindex);
/**
* Return if data is pending in some connection filter at chain
* `sockindex` for connection `data->conn`.
*/
bool Curl_conn_data_pending(struct Curl_easy *data,
int sockindex);
/**
* Return the socket used on data's connection for the index.
* Returns CURL_SOCKET_BAD if not available.
*/
curl_socket_t Curl_conn_get_socket(struct Curl_easy *data, int sockindex);
/**
* Get any select fd flags and the socket filters at chain `sockindex`
* at connection `conn` might be waiting for.
*/
int Curl_conn_get_select_socks(struct Curl_easy *data, int sockindex,
curl_socket_t *socks);
/**
* Receive data through the filter chain at `sockindex` for connection
* `data->conn`. Copy at most `len` bytes into `buf`. Return the
* actuel number of bytes copied or a negative value on error.
* The error code is placed into `*code`.
*/
ssize_t Curl_conn_recv(struct Curl_easy *data, int sockindex, char *buf,
size_t len, CURLcode *code);
/**
* Send `len` bytes of data from `buf` through the filter chain `sockindex`
* at connection `data->conn`. Return the actual number of bytes written
* or a negative value on error.
* The error code is placed into `*code`.
*/
ssize_t Curl_conn_send(struct Curl_easy *data, int sockindex,
const void *buf, size_t len, CURLcode *code);
/**
* The easy handle `data` is being attached to `conn`. This does
* not mean that data will actually do a transfer. Attachment is
* also used for temporary actions on the connection.
*/
void Curl_conn_ev_data_attach(struct connectdata *conn,
struct Curl_easy *data);
/**
* The easy handle `data` is being detached (no longer served)
* by connection `conn`. All filters are informed to release any resources
* related to `data`.
* Note: there may be several `data` attached to a connection at the same
* time.
*/
void Curl_conn_ev_data_detach(struct connectdata *conn,
struct Curl_easy *data);
/**
* Notify connection filters that they need to setup data for
* a transfer.
*/
CURLcode Curl_conn_ev_data_setup(struct Curl_easy *data);
/**
* Notify connection filters that now would be a good time to
* perform any idle, e.g. time related, actions.
*/
CURLcode Curl_conn_ev_data_idle(struct Curl_easy *data);
/**
* Notify connection filters that the transfer represented by `data`
* is donw with sending data (e.g. has uploaded everything).
*/
void Curl_conn_ev_data_done_send(struct Curl_easy *data);
/**
* Notify connection filters that the transfer represented by `data`
* is finished - eventually premature, e.g. before being complete.
*/
void Curl_conn_ev_data_done(struct Curl_easy *data, bool premature);
/**
* Notify connection filters that the transfer of data is paused/unpaused.
*/
CURLcode Curl_conn_ev_data_pause(struct Curl_easy *data, bool do_pause);
/**
* Inform connection filters to update their info in `conn`.
*/
void Curl_conn_ev_update_info(struct Curl_easy *data,
struct connectdata *conn);
/**
* Update connection statistics
*/
void Curl_conn_report_connect_stats(struct Curl_easy *data,
struct connectdata *conn);
/**
* Check if FIRSTSOCKET's cfilter chain deems connection alive.
*/
bool Curl_conn_is_alive(struct Curl_easy *data, struct connectdata *conn,
bool *input_pending);
/**
* Try to upkeep the connection filters at sockindex.
*/
CURLcode Curl_conn_keep_alive(struct Curl_easy *data,
struct connectdata *conn,
int sockindex);
void Curl_conn_get_host(struct Curl_easy *data, int sockindex,
const char **phost, const char **pdisplay_host,
int *pport);
/**
* Get the maximum number of parallel transfers the connection
* expects to be able to handle at `sockindex`.
*/
size_t Curl_conn_get_max_concurrent(struct Curl_easy *data,
struct connectdata *conn,
int sockindex);
/**
* Types and macros used to keep the current easy handle in filter calls,
* allowing for nested invocations. See #10336.
*
* `cf_call_data` is intended to be a member of the cfilter's `ctx` type.
* A filter defines the macro `CF_CTX_CALL_DATA` to give access to that.
*
* With all values 0, the default, this indicates that there is no cfilter
* call with `data` ongoing.
* Macro `CF_DATA_SAVE` preserves the current `cf_call_data` in a local
* variable and sets the `data` given, incrementing the `depth` counter.
*
* Macro `CF_DATA_RESTORE` restores the old values from the local variable,
* while checking that `depth` values are as expected (debug build), catching
* cases where a "lower" RESTORE was not called.
*
* Finally, macro `CF_DATA_CURRENT` gives the easy handle of the current
* invocation.
*/
struct cf_call_data {
struct Curl_easy *data;
#ifdef DEBUGBUILD
int depth;
#endif
};
/**
* define to access the `struct cf_call_data for a cfilter. Normally
* a member in the cfilter's `ctx`.
*
* #define CF_CTX_CALL_DATA(cf) -> struct cf_call_data instance
*/
#ifdef DEBUGBUILD
#define CF_DATA_SAVE(save, cf, data) \
do { \
(save) = CF_CTX_CALL_DATA(cf); \
DEBUGASSERT((save).data == NULL || (save).depth > 0); \
CF_CTX_CALL_DATA(cf).depth++; \
CF_CTX_CALL_DATA(cf).data = (struct Curl_easy *)data; \
} while(0)
#define CF_DATA_RESTORE(cf, save) \
do { \
DEBUGASSERT(CF_CTX_CALL_DATA(cf).depth == (save).depth + 1); \
DEBUGASSERT((save).data == NULL || (save).depth > 0); \
CF_CTX_CALL_DATA(cf) = (save); \
} while(0)
#else /* DEBUGBUILD */
#define CF_DATA_SAVE(save, cf, data) \
do { \
(save) = CF_CTX_CALL_DATA(cf); \
CF_CTX_CALL_DATA(cf).data = (struct Curl_easy *)data; \
} while(0)
#define CF_DATA_RESTORE(cf, save) \
do { \
CF_CTX_CALL_DATA(cf) = (save); \
} while(0)
#endif /* !DEBUGBUILD */
#define CF_DATA_CURRENT(cf) \
((cf)? (CF_CTX_CALL_DATA(cf).data) : NULL)
#endif /* HEADER_CURL_CFILTERS_H */

View file

@ -5,12 +5,12 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2012 - 2016, Linus Nielsen Feltzing, <linus@haxx.se> * Copyright (C) Linus Nielsen Feltzing, <linus@haxx.se>
* Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -19,6 +19,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#include "curl_setup.h" #include "curl_setup.h"
@ -34,92 +36,61 @@
#include "share.h" #include "share.h"
#include "sigpipe.h" #include "sigpipe.h"
#include "connect.h" #include "connect.h"
#include "strcase.h"
/* The last 3 #include files should be in this order */ /* The last 3 #include files should be in this order */
#include "curl_printf.h" #include "curl_printf.h"
#include "curl_memory.h" #include "curl_memory.h"
#include "memdebug.h" #include "memdebug.h"
#ifdef CURLDEBUG #define HASHKEY_SIZE 128
/* 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) { \ static CURLcode bundle_create(struct connectbundle **bundlep)
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
static void conn_llist_dtor(void *user, void *element)
{ {
struct connectdata *conn = element; DEBUGASSERT(*bundlep == NULL);
(void)user; *bundlep = malloc(sizeof(struct connectbundle));
conn->bundle = NULL; if(!*bundlep)
}
static CURLcode bundle_create(struct Curl_easy *data,
struct connectbundle **cb_ptr)
{
(void)data;
DEBUGASSERT(*cb_ptr == NULL);
*cb_ptr = malloc(sizeof(struct connectbundle));
if(!*cb_ptr)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
(*cb_ptr)->num_connections = 0; (*bundlep)->num_connections = 0;
(*cb_ptr)->multiuse = BUNDLE_UNKNOWN; (*bundlep)->multiuse = BUNDLE_UNKNOWN;
Curl_llist_init(&(*cb_ptr)->conn_list, (curl_llist_dtor) conn_llist_dtor); Curl_llist_init(&(*bundlep)->conn_list, NULL);
return CURLE_OK; return CURLE_OK;
} }
static void bundle_destroy(struct connectbundle *cb_ptr) static void bundle_destroy(struct connectbundle *bundle)
{ {
if(!cb_ptr) free(bundle);
return;
Curl_llist_destroy(&cb_ptr->conn_list, NULL);
free(cb_ptr);
} }
/* Add a connection to a bundle */ /* Add a connection to a bundle */
static void bundle_add_conn(struct connectbundle *cb_ptr, static void bundle_add_conn(struct connectbundle *bundle,
struct connectdata *conn) struct connectdata *conn)
{ {
Curl_llist_insert_next(&cb_ptr->conn_list, cb_ptr->conn_list.tail, conn, Curl_llist_insert_next(&bundle->conn_list, bundle->conn_list.tail, conn,
&conn->bundle_node); &conn->bundle_node);
conn->bundle = cb_ptr; conn->bundle = bundle;
cb_ptr->num_connections++; bundle->num_connections++;
} }
/* Remove a connection from a bundle */ /* Remove a connection from a bundle */
static int bundle_remove_conn(struct connectbundle *cb_ptr, static int bundle_remove_conn(struct connectbundle *bundle,
struct connectdata *conn) struct connectdata *conn)
{ {
struct curl_llist_element *curr; struct Curl_llist_element *curr;
curr = cb_ptr->conn_list.head; curr = bundle->conn_list.head;
while(curr) { while(curr) {
if(curr->ptr == conn) { if(curr->ptr == conn) {
Curl_llist_remove(&cb_ptr->conn_list, curr, NULL); Curl_llist_remove(&bundle->conn_list, curr, NULL);
cb_ptr->num_connections--; bundle->num_connections--;
conn->bundle = NULL; conn->bundle = NULL;
return 1; /* we removed a handle */ return 1; /* we removed a handle */
} }
curr = curr->next; curr = curr->next;
} }
DEBUGASSERT(0);
return 0; return 0;
} }
@ -132,23 +103,16 @@ static void free_bundle_hash_entry(void *freethis)
int Curl_conncache_init(struct conncache *connc, int size) int Curl_conncache_init(struct conncache *connc, int size)
{ {
int rc;
/* allocate a new easy handle to use when closing cached connections */ /* allocate a new easy handle to use when closing cached connections */
connc->closure_handle = curl_easy_init(); connc->closure_handle = curl_easy_init();
if(!connc->closure_handle) if(!connc->closure_handle)
return 1; /* bad */ return 1; /* bad */
rc = Curl_hash_init(&connc->hash, size, Curl_hash_str, Curl_hash_init(&connc->hash, size, Curl_hash_str,
Curl_str_key_compare, free_bundle_hash_entry); Curl_str_key_compare, free_bundle_hash_entry);
if(rc) { connc->closure_handle->state.conn_cache = connc;
Curl_close(connc->closure_handle);
connc->closure_handle = NULL;
}
else
connc->closure_handle->state.conn_cache = connc;
return rc; return 0; /* good */
} }
void Curl_conncache_destroy(struct conncache *connc) void Curl_conncache_destroy(struct conncache *connc)
@ -158,29 +122,30 @@ void Curl_conncache_destroy(struct conncache *connc)
} }
/* creates a key to find a bundle for this connection */ /* creates a key to find a bundle for this connection */
static void hashkey(struct connectdata *conn, char *buf, static void hashkey(struct connectdata *conn, char *buf, size_t len)
size_t len) /* something like 128 is fine */
{ {
const char *hostname; const char *hostname;
long port = conn->remote_port;
if(conn->bits.socksproxy) DEBUGASSERT(len >= HASHKEY_SIZE);
hostname = conn->socks_proxy.host.name; #ifndef CURL_DISABLE_PROXY
else if(conn->bits.httpproxy) if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
hostname = conn->http_proxy.host.name; hostname = conn->http_proxy.host.name;
else if(conn->bits.conn_to_host) port = conn->port;
hostname = conn->conn_to_host.name; }
else
#endif
if(conn->bits.conn_to_host)
hostname = conn->conn_to_host.name;
else else
hostname = conn->host.name; hostname = conn->host.name;
DEBUGASSERT(len > 32); /* put the numbers first so that the hostname gets cut off if too long */
#ifdef ENABLE_IPV6
/* put the number first so that the hostname gets cut off if too long */ msnprintf(buf, len, "%u/%ld/%s", conn->scope_id, port, hostname);
msnprintf(buf, len, "%ld%s", conn->port, hostname); #else
} msnprintf(buf, len, "%ld/%s", port, hostname);
#endif
void Curl_conncache_unlock(struct Curl_easy *data) Curl_strntolower(buf, buf, len);
{
CONN_UNLOCK(data);
} }
/* Returns number of connections currently held in the connection cache. /* Returns number of connections currently held in the connection cache.
@ -189,21 +154,9 @@ void Curl_conncache_unlock(struct Curl_easy *data)
size_t Curl_conncache_size(struct Curl_easy *data) size_t Curl_conncache_size(struct Curl_easy *data)
{ {
size_t num; size_t num;
CONN_LOCK(data); CONNCACHE_LOCK(data);
num = data->state.conn_cache->num_conn; num = data->state.conn_cache->num_conn;
CONN_UNLOCK(data); CONNCACHE_UNLOCK(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; return num;
} }
@ -211,13 +164,15 @@ size_t Curl_conncache_bundle_size(struct connectdata *conn)
connectdata struct is setup to use. connectdata struct is setup to use.
**NOTE**: When it returns, it holds the connection cache lock! */ **NOTE**: When it returns, it holds the connection cache lock! */
struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn, struct connectbundle *
struct conncache *connc) Curl_conncache_find_bundle(struct Curl_easy *data,
struct connectdata *conn,
struct conncache *connc)
{ {
struct connectbundle *bundle = NULL; struct connectbundle *bundle = NULL;
CONN_LOCK(conn->data); CONNCACHE_LOCK(data);
if(connc) { if(connc) {
char key[128]; char key[HASHKEY_SIZE];
hashkey(conn, key, sizeof(key)); hashkey(conn, key, sizeof(key));
bundle = Curl_hash_pick(&connc->hash, key, strlen(key)); bundle = Curl_hash_pick(&connc->hash, key, strlen(key));
} }
@ -225,20 +180,18 @@ struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn,
return bundle; return bundle;
} }
static bool conncache_add_bundle(struct conncache *connc, static void *conncache_add_bundle(struct conncache *connc,
char *key, char *key,
struct connectbundle *bundle) struct connectbundle *bundle)
{ {
void *p = Curl_hash_add(&connc->hash, key, strlen(key), bundle); return Curl_hash_add(&connc->hash, key, strlen(key), bundle);
return p?TRUE:FALSE;
} }
static void conncache_remove_bundle(struct conncache *connc, static void conncache_remove_bundle(struct conncache *connc,
struct connectbundle *bundle) struct connectbundle *bundle)
{ {
struct curl_hash_iterator iter; struct Curl_hash_iterator iter;
struct curl_hash_element *he; struct Curl_hash_element *he;
if(!connc) if(!connc)
return; return;
@ -258,54 +211,53 @@ static void conncache_remove_bundle(struct conncache *connc,
} }
} }
CURLcode Curl_conncache_add_conn(struct conncache *connc, CURLcode Curl_conncache_add_conn(struct Curl_easy *data)
struct connectdata *conn)
{ {
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
struct connectbundle *bundle; struct connectbundle *bundle = NULL;
struct connectbundle *new_bundle = NULL; struct connectdata *conn = data->conn;
struct Curl_easy *data = conn->data; struct conncache *connc = data->state.conn_cache;
DEBUGASSERT(conn);
/* *find_bundle() locks the connection cache */ /* *find_bundle() locks the connection cache */
bundle = Curl_conncache_find_bundle(conn, data->state.conn_cache); bundle = Curl_conncache_find_bundle(data, conn, data->state.conn_cache);
if(!bundle) { if(!bundle) {
int rc; char key[HASHKEY_SIZE];
char key[128];
result = bundle_create(data, &new_bundle); result = bundle_create(&bundle);
if(result) { if(result) {
goto unlock; goto unlock;
} }
hashkey(conn, key, sizeof(key)); hashkey(conn, key, sizeof(key));
rc = conncache_add_bundle(data->state.conn_cache, key, new_bundle);
if(!rc) { if(!conncache_add_bundle(data->state.conn_cache, key, bundle)) {
bundle_destroy(new_bundle); bundle_destroy(bundle);
result = CURLE_OUT_OF_MEMORY; result = CURLE_OUT_OF_MEMORY;
goto unlock; goto unlock;
} }
bundle = new_bundle;
} }
bundle_add_conn(bundle, conn); bundle_add_conn(bundle, conn);
conn->connection_id = connc->next_connection_id++; conn->connection_id = connc->next_connection_id++;
connc->num_conn++; connc->num_conn++;
DEBUGF(infof(conn->data, "Added connection %ld. " DEBUGF(infof(data, "Added connection %ld. "
"The cache now contains %zu members\n", "The cache now contains %zu members",
conn->connection_id, connc->num_conn)); conn->connection_id, connc->num_conn));
unlock: unlock:
CONN_UNLOCK(data); CONNCACHE_UNLOCK(data);
return result; return result;
} }
/* /*
* Removes the connectdata object from the connection cache *and* clears the * Removes the connectdata object from the connection cache, but the transfer
* ->data pointer association. Pass TRUE/FALSE in the 'lock' argument * still owns this connection.
* depending on if the parent function already holds the lock or not. *
* Pass TRUE/FALSE in the 'lock' argument depending on if the parent function
* already holds the lock or not.
*/ */
void Curl_conncache_remove_conn(struct Curl_easy *data, void Curl_conncache_remove_conn(struct Curl_easy *data,
struct connectdata *conn, bool lock) struct connectdata *conn, bool lock)
@ -317,7 +269,7 @@ void Curl_conncache_remove_conn(struct Curl_easy *data,
due to a failed connection attempt, before being added to a bundle */ due to a failed connection attempt, before being added to a bundle */
if(bundle) { if(bundle) {
if(lock) { if(lock) {
CONN_LOCK(data); CONNCACHE_LOCK(data);
} }
bundle_remove_conn(bundle, conn); bundle_remove_conn(bundle, conn);
if(bundle->num_connections == 0) if(bundle->num_connections == 0)
@ -325,12 +277,11 @@ void Curl_conncache_remove_conn(struct Curl_easy *data,
conn->bundle = NULL; /* removed from it */ conn->bundle = NULL; /* removed from it */
if(connc) { if(connc) {
connc->num_conn--; connc->num_conn--;
DEBUGF(infof(data, "The cache now contains %zu members\n", DEBUGF(infof(data, "The cache now contains %zu members",
connc->num_conn)); connc->num_conn));
} }
conn->data = NULL; /* clear the association */
if(lock) { if(lock) {
CONN_UNLOCK(data); CONNCACHE_UNLOCK(data);
} }
} }
} }
@ -350,16 +301,17 @@ void Curl_conncache_remove_conn(struct Curl_easy *data,
bool Curl_conncache_foreach(struct Curl_easy *data, bool Curl_conncache_foreach(struct Curl_easy *data,
struct conncache *connc, struct conncache *connc,
void *param, void *param,
int (*func)(struct connectdata *conn, void *param)) int (*func)(struct Curl_easy *data,
struct connectdata *conn, void *param))
{ {
struct curl_hash_iterator iter; struct Curl_hash_iterator iter;
struct curl_llist_element *curr; struct Curl_llist_element *curr;
struct curl_hash_element *he; struct Curl_hash_element *he;
if(!connc) if(!connc)
return FALSE; return FALSE;
CONN_LOCK(data); CONNCACHE_LOCK(data);
Curl_hash_start_iterate(&connc->hash, &iter); Curl_hash_start_iterate(&connc->hash, &iter);
he = Curl_hash_next_element(&iter); he = Curl_hash_next_element(&iter);
@ -376,13 +328,13 @@ bool Curl_conncache_foreach(struct Curl_easy *data,
struct connectdata *conn = curr->ptr; struct connectdata *conn = curr->ptr;
curr = curr->next; curr = curr->next;
if(1 == func(conn, param)) { if(1 == func(data, conn, param)) {
CONN_UNLOCK(data); CONNCACHE_UNLOCK(data);
return TRUE; return TRUE;
} }
} }
} }
CONN_UNLOCK(data); CONNCACHE_UNLOCK(data);
return FALSE; return FALSE;
} }
@ -395,15 +347,15 @@ bool Curl_conncache_foreach(struct Curl_easy *data,
static struct connectdata * static struct connectdata *
conncache_find_first_connection(struct conncache *connc) conncache_find_first_connection(struct conncache *connc)
{ {
struct curl_hash_iterator iter; struct Curl_hash_iterator iter;
struct curl_hash_element *he; struct Curl_hash_element *he;
struct connectbundle *bundle; struct connectbundle *bundle;
Curl_hash_start_iterate(&connc->hash, &iter); Curl_hash_start_iterate(&connc->hash, &iter);
he = Curl_hash_next_element(&iter); he = Curl_hash_next_element(&iter);
while(he) { while(he) {
struct curl_llist_element *curr; struct Curl_llist_element *curr;
bundle = he->ptr; bundle = he->ptr;
curr = bundle->conn_list.head; curr = bundle->conn_list.head;
@ -423,26 +375,24 @@ conncache_find_first_connection(struct conncache *connc)
* *
* Return TRUE if stored, FALSE if closed. * 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. */ /* data->multi->maxconnects can be negative, deal with it. */
size_t maxconnects = size_t maxconnects =
(data->multi->maxconnects < 0) ? data->multi->num_easy * 4: (data->multi->maxconnects < 0) ? data->multi->num_easy * 4:
data->multi->maxconnects; data->multi->maxconnects;
struct connectdata *conn_candidate = NULL; struct connectdata *conn_candidate = NULL;
conn->data = NULL; /* no owner anymore */
conn->lastused = Curl_now(); /* it was used up until now */ conn->lastused = Curl_now(); /* it was used up until now */
if(maxconnects > 0 && if(maxconnects > 0 &&
Curl_conncache_size(data) > maxconnects) { Curl_conncache_size(data) > maxconnects) {
infof(data, "Connection cache is full, closing the oldest one.\n"); infof(data, "Connection cache is full, closing the oldest one");
conn_candidate = Curl_conncache_extract_oldest(data); conn_candidate = Curl_conncache_extract_oldest(data);
if(conn_candidate) { if(conn_candidate) {
/* the winner gets the honour of being disconnected */ /* the winner gets the honour of being disconnected */
(void)Curl_disconnect(data, conn_candidate, /* dead_connection */ FALSE); Curl_disconnect(data, conn_candidate, /* dead_connection */ FALSE);
} }
} }
@ -463,7 +413,7 @@ struct connectdata *
Curl_conncache_extract_bundle(struct Curl_easy *data, Curl_conncache_extract_bundle(struct Curl_easy *data,
struct connectbundle *bundle) struct connectbundle *bundle)
{ {
struct curl_llist_element *curr; struct Curl_llist_element *curr;
timediff_t highscore = -1; timediff_t highscore = -1;
timediff_t score; timediff_t score;
struct curltime now; struct curltime now;
@ -478,7 +428,7 @@ Curl_conncache_extract_bundle(struct Curl_easy *data,
while(curr) { while(curr) {
conn = curr->ptr; conn = curr->ptr;
if(!CONN_INUSE(conn) && !conn->data) { if(!CONN_INUSE(conn)) {
/* Set higher score for the age passed since the connection was used */ /* Set higher score for the age passed since the connection was used */
score = Curl_timediff(now, conn->lastused); score = Curl_timediff(now, conn->lastused);
@ -493,9 +443,8 @@ Curl_conncache_extract_bundle(struct Curl_easy *data,
/* remove it to prevent another thread from nicking it */ /* remove it to prevent another thread from nicking it */
bundle_remove_conn(bundle, conn_candidate); bundle_remove_conn(bundle, conn_candidate);
data->state.conn_cache->num_conn--; data->state.conn_cache->num_conn--;
DEBUGF(infof(data, "The cache now contains %zu members\n", DEBUGF(infof(data, "The cache now contains %zu members",
data->state.conn_cache->num_conn)); data->state.conn_cache->num_conn));
conn_candidate->data = data; /* associate! */
} }
return conn_candidate; return conn_candidate;
@ -511,9 +460,9 @@ struct connectdata *
Curl_conncache_extract_oldest(struct Curl_easy *data) Curl_conncache_extract_oldest(struct Curl_easy *data)
{ {
struct conncache *connc = data->state.conn_cache; struct conncache *connc = data->state.conn_cache;
struct curl_hash_iterator iter; struct Curl_hash_iterator iter;
struct curl_llist_element *curr; struct Curl_llist_element *curr;
struct curl_hash_element *he; struct Curl_hash_element *he;
timediff_t highscore =- 1; timediff_t highscore =- 1;
timediff_t score; timediff_t score;
struct curltime now; struct curltime now;
@ -523,7 +472,7 @@ Curl_conncache_extract_oldest(struct Curl_easy *data)
now = Curl_now(); now = Curl_now();
CONN_LOCK(data); CONNCACHE_LOCK(data);
Curl_hash_start_iterate(&connc->hash, &iter); Curl_hash_start_iterate(&connc->hash, &iter);
he = Curl_hash_next_element(&iter); he = Curl_hash_next_element(&iter);
@ -536,7 +485,8 @@ Curl_conncache_extract_oldest(struct Curl_easy *data)
while(curr) { while(curr) {
conn = curr->ptr; conn = curr->ptr;
if(!CONN_INUSE(conn) && !conn->data) { if(!CONN_INUSE(conn) && !conn->bits.close &&
!conn->connect_only) {
/* Set higher score for the age passed since the connection was used */ /* Set higher score for the age passed since the connection was used */
score = Curl_timediff(now, conn->lastused); score = Curl_timediff(now, conn->lastused);
@ -555,11 +505,10 @@ Curl_conncache_extract_oldest(struct Curl_easy *data)
/* remove it to prevent another thread from nicking it */ /* remove it to prevent another thread from nicking it */
bundle_remove_conn(bundle_candidate, conn_candidate); bundle_remove_conn(bundle_candidate, conn_candidate);
connc->num_conn--; connc->num_conn--;
DEBUGF(infof(data, "The cache now contains %zu members\n", DEBUGF(infof(data, "The cache now contains %zu members",
connc->num_conn)); connc->num_conn));
conn_candidate->data = data; /* associate! */
} }
CONN_UNLOCK(data); CONNCACHE_UNLOCK(data);
return conn_candidate; return conn_candidate;
} }
@ -567,39 +516,41 @@ Curl_conncache_extract_oldest(struct Curl_easy *data)
void Curl_conncache_close_all_connections(struct conncache *connc) void Curl_conncache_close_all_connections(struct conncache *connc)
{ {
struct connectdata *conn; struct connectdata *conn;
char buffer[READBUFFER_MIN + 1];
SIGPIPE_VARIABLE(pipe_st);
if(!connc->closure_handle)
return;
connc->closure_handle->state.buffer = buffer;
connc->closure_handle->set.buffer_size = READBUFFER_MIN;
conn = conncache_find_first_connection(connc); conn = conncache_find_first_connection(connc);
while(conn) { while(conn) {
SIGPIPE_VARIABLE(pipe_st); sigpipe_ignore(connc->closure_handle, &pipe_st);
conn->data = connc->closure_handle;
sigpipe_ignore(conn->data, &pipe_st);
/* This will remove the connection from the cache */ /* This will remove the connection from the cache */
connclose(conn, "kill all"); connclose(conn, "kill all");
(void)Curl_disconnect(connc->closure_handle, conn, FALSE); Curl_conncache_remove_conn(connc->closure_handle, conn, TRUE);
Curl_disconnect(connc->closure_handle, conn, FALSE);
sigpipe_restore(&pipe_st); sigpipe_restore(&pipe_st);
conn = conncache_find_first_connection(connc); conn = conncache_find_first_connection(connc);
} }
if(connc->closure_handle) { connc->closure_handle->state.buffer = NULL;
SIGPIPE_VARIABLE(pipe_st); sigpipe_ignore(connc->closure_handle, &pipe_st);
sigpipe_ignore(connc->closure_handle, &pipe_st);
Curl_hostcache_clean(connc->closure_handle, Curl_hostcache_clean(connc->closure_handle,
connc->closure_handle->dns.hostcache); connc->closure_handle->dns.hostcache);
Curl_close(connc->closure_handle); Curl_close(&connc->closure_handle);
sigpipe_restore(&pipe_st); sigpipe_restore(&pipe_st);
}
} }
#if 0 #if 0
/* Useful for debugging the connection cache */ /* Useful for debugging the connection cache */
void Curl_conncache_print(struct conncache *connc) void Curl_conncache_print(struct conncache *connc)
{ {
struct curl_hash_iterator iter; struct Curl_hash_iterator iter;
struct curl_llist_element *curr; struct Curl_llist_element *curr;
struct curl_hash_element *he; struct Curl_hash_element *he;
if(!connc) if(!connc)
return; return;

View file

@ -7,12 +7,12 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2015 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2012 - 2014, Linus Nielsen Feltzing, <linus@haxx.se> * Copyright (C) Linus Nielsen Feltzing, <linus@haxx.se>
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -21,6 +21,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
/* /*
@ -29,8 +31,13 @@
* be shared. * be shared.
*/ */
#include <curl/curl.h>
#include "timeval.h"
struct connectdata;
struct conncache { struct conncache {
struct curl_hash hash; struct Curl_hash hash;
size_t num_conn; size_t num_conn;
long next_connection_id; long next_connection_id;
struct curltime last_cleanup; struct curltime last_cleanup;
@ -42,10 +49,38 @@ struct conncache {
#define BUNDLE_UNKNOWN 0 /* initial value */ #define BUNDLE_UNKNOWN 0 /* initial value */
#define BUNDLE_MULTIPLEX 2 #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 CONNCACHE_LOCK(x) \
do { \
if((x)->share) { \
Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, \
CURL_LOCK_ACCESS_SINGLE); \
DEBUGASSERT(!(x)->state.conncache_lock); \
(x)->state.conncache_lock = TRUE; \
} \
} while(0)
#define CONNCACHE_UNLOCK(x) \
do { \
if((x)->share) { \
DEBUGASSERT((x)->state.conncache_lock); \
(x)->state.conncache_lock = FALSE; \
Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT); \
} \
} while(0)
#else
#define CONNCACHE_LOCK(x) if((x)->share) \
Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE)
#define CONNCACHE_UNLOCK(x) if((x)->share) \
Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT)
#endif
struct connectbundle { struct connectbundle {
int multiuse; /* supports multi-use */ int multiuse; /* supports multi-use */
size_t num_connections; /* Number of connections in the bundle */ size_t num_connections; /* Number of connections in the bundle */
struct curl_llist conn_list; /* The connectdata members of the bundle */ struct Curl_llist conn_list; /* The connectdata members of the bundle */
}; };
/* returns 1 on error, 0 is fine */ /* returns 1 on error, 0 is fine */
@ -53,23 +88,23 @@ int Curl_conncache_init(struct conncache *, int size);
void Curl_conncache_destroy(struct conncache *connc); void Curl_conncache_destroy(struct conncache *connc);
/* return the correct bundle, to a host or a proxy */ /* return the correct bundle, to a host or a proxy */
struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn, struct connectbundle *Curl_conncache_find_bundle(struct Curl_easy *data,
struct connectdata *conn,
struct conncache *connc); struct conncache *connc);
void Curl_conncache_unlock(struct Curl_easy *data);
/* returns number of connections currently held in the connection cache */ /* returns number of connections currently held in the connection cache */
size_t Curl_conncache_size(struct Curl_easy *data); 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,
CURLcode Curl_conncache_add_conn(struct conncache *connc, struct connectdata *conn);
struct connectdata *conn) WARN_UNUSED_RESULT; CURLcode Curl_conncache_add_conn(struct Curl_easy *data) WARN_UNUSED_RESULT;
void Curl_conncache_remove_conn(struct Curl_easy *data, void Curl_conncache_remove_conn(struct Curl_easy *data,
struct connectdata *conn, struct connectdata *conn,
bool lock); bool lock);
bool Curl_conncache_foreach(struct Curl_easy *data, bool Curl_conncache_foreach(struct Curl_easy *data,
struct conncache *connc, struct conncache *connc,
void *param, void *param,
int (*func)(struct connectdata *conn, int (*func)(struct Curl_easy *data,
struct connectdata *conn,
void *param)); void *param));
struct connectdata * struct connectdata *

File diff suppressed because it is too large Load diff

View file

@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#include "curl_setup.h" #include "curl_setup.h"
@ -27,12 +29,7 @@
#include "sockaddr.h" #include "sockaddr.h"
#include "timeval.h" #include "timeval.h"
CURLcode Curl_is_connected(struct connectdata *conn, struct Curl_dns_entry;
int sockindex,
bool *connected);
CURLcode Curl_connecthost(struct connectdata *conn,
const struct Curl_dns_entry *host);
/* generic function that returns how much time there's left to run, according /* generic function that returns how much time there's left to run, according
to the timeouts set */ to the timeouts set */
@ -51,60 +48,11 @@ timediff_t Curl_timeleft(struct Curl_easy *data,
curl_socket_t Curl_getconnectinfo(struct Curl_easy *data, curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
struct connectdata **connp); struct connectdata **connp);
/* bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen,
* Check if a connection seems to be alive. char *addr, int *port);
*/
bool Curl_connalive(struct connectdata *conn);
#ifdef USE_WINSOCK void Curl_persistconninfo(struct Curl_easy *data, struct connectdata *conn,
/* When you run a program that uses the Windows Sockets API, you may char *local_ip, int local_port);
experience slow performance when you copy data to a TCP server.
https://support.microsoft.com/kb/823764
Work-around: Make the Socket Send Buffer Size Larger Than the Program Send
Buffer Size
*/
void Curl_sndbufset(curl_socket_t sockfd);
#else
#define Curl_sndbufset(y) Curl_nop_stmt
#endif
void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd);
void Curl_persistconninfo(struct connectdata *conn);
int Curl_closesocket(struct connectdata *conn, curl_socket_t sock);
/*
* The Curl_sockaddr_ex structure is basically libcurl's external API
* curl_sockaddr structure with enough space available to directly hold any
* protocol-specific address structures. The variable declared here will be
* used to pass / receive data to/from the fopensocket callback if this has
* been set, before that, it is initialized from parameters.
*/
struct Curl_sockaddr_ex {
int family;
int socktype;
int protocol;
unsigned int addrlen;
union {
struct sockaddr addr;
struct Curl_sockaddr_storage buff;
} _sa_ex_u;
};
#define sa_addr _sa_ex_u.addr
/*
* Create a socket based on info from 'conn' and 'ai'.
*
* Fill in 'addr' and 'sockfd' accordingly if OK is returned. If the open
* socket callback is set, used that!
*
*/
CURLcode Curl_socket(struct connectdata *conn,
const Curl_addrinfo *ai,
struct Curl_sockaddr_ex *addr,
curl_socket_t *sockfd);
/* /*
* Curl_conncontrol() marks the end of a connection/stream. The 'closeit' * Curl_conncontrol() marks the end of a connection/stream. The 'closeit'
@ -139,6 +87,71 @@ void Curl_conncontrol(struct connectdata *conn,
#define connkeep(x,y) Curl_conncontrol(x, CONNCTRL_KEEP) #define connkeep(x,y) Curl_conncontrol(x, CONNCTRL_KEEP)
#endif #endif
bool Curl_conn_data_pending(struct connectdata *conn, int sockindex); /**
* Create a cfilter for making an "ip" connection to the
* given address, using parameters from `conn`. The "ip" connection
* can be a TCP socket, a UDP socket or even a QUIC connection.
*
* It MUST use only the supplied `ai` for its connection attempt.
*
* Such a filter may be used in "happy eyeball" scenarios, and its
* `connect` implementation needs to support non-blocking. Once connected,
* it MAY be installed in the connection filter chain to serve transfers.
*/
typedef CURLcode cf_ip_connect_create(struct Curl_cfilter **pcf,
struct Curl_easy *data,
struct connectdata *conn,
const struct Curl_addrinfo *ai,
int transport);
/**
* Create a happy eyeball connection filter that uses the, once resolved,
* address information to connect on ip families based on connection
* configuration.
* @param pcf output, the created cfilter
* @param data easy handle used in creation
* @param conn connection the filter is created for
* @param cf_create method to create the sub-filters performing the
* actual connects.
*/
CURLcode
Curl_cf_happy_eyeballs_create(struct Curl_cfilter **pcf,
struct Curl_easy *data,
struct connectdata *conn,
cf_ip_connect_create *cf_create,
const struct Curl_dns_entry *remotehost,
int transport);
CURLcode Curl_cf_setup_add(struct Curl_easy *data,
struct connectdata *conn,
int sockindex,
const struct Curl_dns_entry *remotehost,
int transport,
int ssl_mode);
CURLcode Curl_cf_setup_insert_after(struct Curl_cfilter *cf_at,
struct Curl_easy *data,
const struct Curl_dns_entry *remotehost,
int transport,
int ssl_mode);
/**
* Setup the cfilters at `sockindex` in connection `conn`.
* If no filter chain is installed yet, inspects the configuration
* in `data` and `conn? to install a suitable filter chain.
*/
CURLcode Curl_conn_setup(struct Curl_easy *data,
struct connectdata *conn,
int sockindex,
const struct Curl_dns_entry *remotehost,
int ssl_mode);
extern struct Curl_cftype Curl_cft_happy_eyeballs;
extern struct Curl_cftype Curl_cft_setup;
#ifdef DEBUGBUILD
void Curl_debug_set_transport_provider(int transport,
cf_ip_connect_create *cf_create);
#endif
#endif /* HEADER_CURL_CONNECT_H */ #endif /* HEADER_CURL_CONNECT_H */

View file

@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#include "curl_setup.h" #include "curl_setup.h"
@ -26,16 +28,24 @@
#include <curl/curl.h> #include <curl/curl.h>
#include <stddef.h> #include <stddef.h>
#ifdef HAVE_ZLIB_H #ifdef HAVE_LIBZ
#include <zlib.h> #include <zlib.h>
#ifdef __SYMBIAN32__
/* zlib pollutes the namespace with this definition */
#undef WIN32
#endif
#endif #endif
#ifdef HAVE_BROTLI #ifdef HAVE_BROTLI
#if defined(__GNUC__)
/* Ignore -Wvla warnings in brotli headers */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wvla"
#endif
#include <brotli/decode.h> #include <brotli/decode.h>
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
#endif
#ifdef HAVE_ZSTD
#include <zstd.h>
#endif #endif
#include "sendf.h" #include "sendf.h"
@ -80,12 +90,13 @@ typedef enum {
ZLIB_INIT_GZIP /* initialized in transparent gzip mode */ ZLIB_INIT_GZIP /* initialized in transparent gzip mode */
} zlibInitState; } zlibInitState;
/* Writer parameters. */ /* Deflate and gzip writer. */
typedef struct { struct zlib_writer {
struct contenc_writer super;
zlibInitState zlib_init; /* zlib init state */ zlibInitState zlib_init; /* zlib init state */
uInt trailerlen; /* Remaining trailer byte count. */ uInt trailerlen; /* Remaining trailer byte count. */
z_stream z; /* State structure for zlib. */ z_stream z; /* State structure for zlib. */
} zlib_params; };
static voidpf static voidpf
@ -104,9 +115,8 @@ zfree_cb(voidpf opaque, voidpf ptr)
} }
static CURLcode static CURLcode
process_zlib_error(struct connectdata *conn, z_stream *z) process_zlib_error(struct Curl_easy *data, z_stream *z)
{ {
struct Curl_easy *data = conn->data;
if(z->msg) if(z->msg)
failf(data, "Error while processing content unencoding: %s", failf(data, "Error while processing content unencoding: %s",
z->msg); z->msg);
@ -118,7 +128,7 @@ process_zlib_error(struct connectdata *conn, z_stream *z)
} }
static CURLcode static CURLcode
exit_zlib(struct connectdata *conn, exit_zlib(struct Curl_easy *data,
z_stream *z, zlibInitState *zlib_init, CURLcode result) z_stream *z, zlibInitState *zlib_init, CURLcode result)
{ {
if(*zlib_init == ZLIB_GZIP_HEADER) if(*zlib_init == ZLIB_GZIP_HEADER)
@ -126,14 +136,15 @@ exit_zlib(struct connectdata *conn,
if(*zlib_init != ZLIB_UNINIT) { if(*zlib_init != ZLIB_UNINIT) {
if(inflateEnd(z) != Z_OK && result == CURLE_OK) if(inflateEnd(z) != Z_OK && result == CURLE_OK)
result = process_zlib_error(conn, z); result = process_zlib_error(data, z);
*zlib_init = ZLIB_UNINIT; *zlib_init = ZLIB_UNINIT;
} }
return result; return result;
} }
static CURLcode process_trailer(struct connectdata *conn, zlib_params *zp) static CURLcode process_trailer(struct Curl_easy *data,
struct zlib_writer *zp)
{ {
z_stream *z = &zp->z; z_stream *z = &zp->z;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
@ -148,7 +159,7 @@ static CURLcode process_trailer(struct connectdata *conn, zlib_params *zp)
if(z->avail_in) if(z->avail_in)
result = CURLE_WRITE_ERROR; result = CURLE_WRITE_ERROR;
if(result || !zp->trailerlen) if(result || !zp->trailerlen)
result = exit_zlib(conn, z, &zp->zlib_init, result); result = exit_zlib(data, z, &zp->zlib_init, result);
else { else {
/* Only occurs for gzip with zlib < 1.2.0.4 or raw deflate. */ /* Only occurs for gzip with zlib < 1.2.0.4 or raw deflate. */
zp->zlib_init = ZLIB_EXTERNAL_TRAILER; zp->zlib_init = ZLIB_EXTERNAL_TRAILER;
@ -156,10 +167,11 @@ static CURLcode process_trailer(struct connectdata *conn, zlib_params *zp)
return result; return result;
} }
static CURLcode inflate_stream(struct connectdata *conn, static CURLcode inflate_stream(struct Curl_easy *data,
contenc_writer *writer, zlibInitState started) struct contenc_writer *writer,
zlibInitState started)
{ {
zlib_params *zp = (zlib_params *) &writer->params; struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */ z_stream *z = &zp->z; /* zlib state structure */
uInt nread = z->avail_in; uInt nread = z->avail_in;
Bytef *orig_in = z->next_in; Bytef *orig_in = z->next_in;
@ -172,13 +184,13 @@ static CURLcode inflate_stream(struct connectdata *conn,
zp->zlib_init != ZLIB_INFLATING && zp->zlib_init != ZLIB_INFLATING &&
zp->zlib_init != ZLIB_INIT_GZIP && zp->zlib_init != ZLIB_INIT_GZIP &&
zp->zlib_init != ZLIB_GZIP_INFLATING) zp->zlib_init != ZLIB_GZIP_INFLATING)
return exit_zlib(conn, z, &zp->zlib_init, CURLE_WRITE_ERROR); return exit_zlib(data, z, &zp->zlib_init, CURLE_WRITE_ERROR);
/* Dynamically allocate a buffer for decompression because it's uncommonly /* Dynamically allocate a buffer for decompression because it's uncommonly
large to hold on the stack */ large to hold on the stack */
decomp = malloc(DSIZ); decomp = malloc(DSIZ);
if(decomp == NULL) if(!decomp)
return exit_zlib(conn, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY); return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
/* because the buffer size is fixed, iteratively decompress and transfer to /* because the buffer size is fixed, iteratively decompress and transfer to
the client via downstream_write function. */ the client via downstream_write function. */
@ -202,10 +214,10 @@ static CURLcode inflate_stream(struct connectdata *conn,
if(z->avail_out != DSIZ) { if(z->avail_out != DSIZ) {
if(status == Z_OK || status == Z_STREAM_END) { if(status == Z_OK || status == Z_STREAM_END) {
zp->zlib_init = started; /* Data started. */ zp->zlib_init = started; /* Data started. */
result = Curl_unencode_write(conn, writer->downstream, decomp, result = Curl_unencode_write(data, writer->downstream, decomp,
DSIZ - z->avail_out); DSIZ - z->avail_out);
if(result) { if(result) {
exit_zlib(conn, z, &zp->zlib_init, result); exit_zlib(data, z, &zp->zlib_init, result);
break; break;
} }
} }
@ -221,7 +233,7 @@ static CURLcode inflate_stream(struct connectdata *conn,
/* No more data to flush: just exit loop. */ /* No more data to flush: just exit loop. */
break; break;
case Z_STREAM_END: case Z_STREAM_END:
result = process_trailer(conn, zp); result = process_trailer(data, zp);
break; break;
case Z_DATA_ERROR: case Z_DATA_ERROR:
/* some servers seem to not generate zlib headers, so this is an attempt /* some servers seem to not generate zlib headers, so this is an attempt
@ -239,9 +251,10 @@ static CURLcode inflate_stream(struct connectdata *conn,
} }
zp->zlib_init = ZLIB_UNINIT; /* inflateEnd() already called. */ zp->zlib_init = ZLIB_UNINIT; /* inflateEnd() already called. */
} }
/* FALLTHROUGH */ result = exit_zlib(data, z, &zp->zlib_init, process_zlib_error(data, z));
break;
default: default:
result = exit_zlib(conn, z, &zp->zlib_init, process_zlib_error(conn, z)); result = exit_zlib(data, z, &zp->zlib_init, process_zlib_error(data, z));
break; break;
} }
} }
@ -258,10 +271,10 @@ static CURLcode inflate_stream(struct connectdata *conn,
/* Deflate handler. */ /* Deflate handler. */
static CURLcode deflate_init_writer(struct connectdata *conn, static CURLcode deflate_init_writer(struct Curl_easy *data,
contenc_writer *writer) struct contenc_writer *writer)
{ {
zlib_params *zp = (zlib_params *) &writer->params; struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */ z_stream *z = &zp->z; /* zlib state structure */
if(!writer->downstream) if(!writer->downstream)
@ -272,16 +285,16 @@ static CURLcode deflate_init_writer(struct connectdata *conn,
z->zfree = (free_func) zfree_cb; z->zfree = (free_func) zfree_cb;
if(inflateInit(z) != Z_OK) if(inflateInit(z) != Z_OK)
return process_zlib_error(conn, z); return process_zlib_error(data, z);
zp->zlib_init = ZLIB_INIT; zp->zlib_init = ZLIB_INIT;
return CURLE_OK; return CURLE_OK;
} }
static CURLcode deflate_unencode_write(struct connectdata *conn, static CURLcode deflate_unencode_write(struct Curl_easy *data,
contenc_writer *writer, struct contenc_writer *writer,
const char *buf, size_t nbytes) const char *buf, size_t nbytes)
{ {
zlib_params *zp = (zlib_params *) &writer->params; struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */ z_stream *z = &zp->z; /* zlib state structure */
/* Set the compressed input when this function is called */ /* Set the compressed input when this function is called */
@ -289,36 +302,36 @@ static CURLcode deflate_unencode_write(struct connectdata *conn,
z->avail_in = (uInt) nbytes; z->avail_in = (uInt) nbytes;
if(zp->zlib_init == ZLIB_EXTERNAL_TRAILER) if(zp->zlib_init == ZLIB_EXTERNAL_TRAILER)
return process_trailer(conn, zp); return process_trailer(data, zp);
/* Now uncompress the data */ /* Now uncompress the data */
return inflate_stream(conn, writer, ZLIB_INFLATING); return inflate_stream(data, writer, ZLIB_INFLATING);
} }
static void deflate_close_writer(struct connectdata *conn, static void deflate_close_writer(struct Curl_easy *data,
contenc_writer *writer) struct contenc_writer *writer)
{ {
zlib_params *zp = (zlib_params *) &writer->params; struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */ z_stream *z = &zp->z; /* zlib state structure */
exit_zlib(conn, z, &zp->zlib_init, CURLE_OK); exit_zlib(data, z, &zp->zlib_init, CURLE_OK);
} }
static const content_encoding deflate_encoding = { static const struct content_encoding deflate_encoding = {
"deflate", "deflate",
NULL, NULL,
deflate_init_writer, deflate_init_writer,
deflate_unencode_write, deflate_unencode_write,
deflate_close_writer, deflate_close_writer,
sizeof(zlib_params) sizeof(struct zlib_writer)
}; };
/* Gzip handler. */ /* Gzip handler. */
static CURLcode gzip_init_writer(struct connectdata *conn, static CURLcode gzip_init_writer(struct Curl_easy *data,
contenc_writer *writer) struct contenc_writer *writer)
{ {
zlib_params *zp = (zlib_params *) &writer->params; struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */ z_stream *z = &zp->z; /* zlib state structure */
if(!writer->downstream) if(!writer->downstream)
@ -331,14 +344,14 @@ static CURLcode gzip_init_writer(struct connectdata *conn,
if(strcmp(zlibVersion(), "1.2.0.4") >= 0) { if(strcmp(zlibVersion(), "1.2.0.4") >= 0) {
/* zlib ver. >= 1.2.0.4 supports transparent gzip decompressing */ /* zlib ver. >= 1.2.0.4 supports transparent gzip decompressing */
if(inflateInit2(z, MAX_WBITS + 32) != Z_OK) { if(inflateInit2(z, MAX_WBITS + 32) != Z_OK) {
return process_zlib_error(conn, z); return process_zlib_error(data, z);
} }
zp->zlib_init = ZLIB_INIT_GZIP; /* Transparent gzip decompress state */ zp->zlib_init = ZLIB_INIT_GZIP; /* Transparent gzip decompress state */
} }
else { else {
/* we must parse the gzip header and trailer ourselves */ /* we must parse the gzip header and trailer ourselves */
if(inflateInit2(z, -MAX_WBITS) != Z_OK) { if(inflateInit2(z, -MAX_WBITS) != Z_OK) {
return process_zlib_error(conn, z); return process_zlib_error(data, z);
} }
zp->trailerlen = 8; /* A CRC-32 and a 32-bit input size (RFC 1952, 2.2) */ zp->trailerlen = 8; /* A CRC-32 and a 32-bit input size (RFC 1952, 2.2) */
zp->zlib_init = ZLIB_INIT; /* Initial call state */ zp->zlib_init = ZLIB_INIT; /* Initial call state */
@ -431,11 +444,11 @@ static enum {
} }
#endif #endif
static CURLcode gzip_unencode_write(struct connectdata *conn, static CURLcode gzip_unencode_write(struct Curl_easy *data,
contenc_writer *writer, struct contenc_writer *writer,
const char *buf, size_t nbytes) const char *buf, size_t nbytes)
{ {
zlib_params *zp = (zlib_params *) &writer->params; struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */ z_stream *z = &zp->z; /* zlib state structure */
if(zp->zlib_init == ZLIB_INIT_GZIP) { if(zp->zlib_init == ZLIB_INIT_GZIP) {
@ -443,13 +456,13 @@ static CURLcode gzip_unencode_write(struct connectdata *conn,
z->next_in = (Bytef *) buf; z->next_in = (Bytef *) buf;
z->avail_in = (uInt) nbytes; z->avail_in = (uInt) nbytes;
/* Now uncompress the data */ /* Now uncompress the data */
return inflate_stream(conn, writer, ZLIB_INIT_GZIP); return inflate_stream(data, writer, ZLIB_INIT_GZIP);
} }
#ifndef OLD_ZLIB_SUPPORT #ifndef OLD_ZLIB_SUPPORT
/* Support for old zlib versions is compiled away and we are running with /* Support for old zlib versions is compiled away and we are running with
an old version, so return an error. */ an old version, so return an error. */
return exit_zlib(conn, z, &zp->zlib_init, CURLE_WRITE_ERROR); return exit_zlib(data, z, &zp->zlib_init, CURLE_WRITE_ERROR);
#else #else
/* This next mess is to get around the potential case where there isn't /* This next mess is to get around the potential case where there isn't
@ -486,8 +499,8 @@ static CURLcode gzip_unencode_write(struct connectdata *conn,
*/ */
z->avail_in = (uInt) nbytes; z->avail_in = (uInt) nbytes;
z->next_in = malloc(z->avail_in); z->next_in = malloc(z->avail_in);
if(z->next_in == NULL) { if(!z->next_in) {
return exit_zlib(conn, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY); return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
} }
memcpy(z->next_in, buf, z->avail_in); memcpy(z->next_in, buf, z->avail_in);
zp->zlib_init = ZLIB_GZIP_HEADER; /* Need more gzip header data state */ zp->zlib_init = ZLIB_GZIP_HEADER; /* Need more gzip header data state */
@ -496,7 +509,7 @@ static CURLcode gzip_unencode_write(struct connectdata *conn,
case GZIP_BAD: case GZIP_BAD:
default: default:
return exit_zlib(conn, z, &zp->zlib_init, process_zlib_error(conn, z)); return exit_zlib(data, z, &zp->zlib_init, process_zlib_error(data, z));
} }
} }
@ -508,8 +521,8 @@ static CURLcode gzip_unencode_write(struct connectdata *conn,
ssize_t hlen; ssize_t hlen;
z->avail_in += (uInt) nbytes; z->avail_in += (uInt) nbytes;
z->next_in = Curl_saferealloc(z->next_in, z->avail_in); z->next_in = Curl_saferealloc(z->next_in, z->avail_in);
if(z->next_in == NULL) { if(!z->next_in) {
return exit_zlib(conn, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY); return exit_zlib(data, z, &zp->zlib_init, CURLE_OUT_OF_MEMORY);
} }
/* Append the new block of data to the previous one */ /* Append the new block of data to the previous one */
memcpy(z->next_in + z->avail_in - nbytes, buf, nbytes); memcpy(z->next_in + z->avail_in - nbytes, buf, nbytes);
@ -530,7 +543,7 @@ static CURLcode gzip_unencode_write(struct connectdata *conn,
case GZIP_BAD: case GZIP_BAD:
default: default:
return exit_zlib(conn, z, &zp->zlib_init, process_zlib_error(conn, z)); return exit_zlib(data, z, &zp->zlib_init, process_zlib_error(data, z));
} }
} }
@ -539,7 +552,7 @@ static CURLcode gzip_unencode_write(struct connectdata *conn,
case ZLIB_EXTERNAL_TRAILER: case ZLIB_EXTERNAL_TRAILER:
z->next_in = (Bytef *) buf; z->next_in = (Bytef *) buf;
z->avail_in = (uInt) nbytes; z->avail_in = (uInt) nbytes;
return process_trailer(conn, zp); return process_trailer(data, zp);
case ZLIB_GZIP_INFLATING: case ZLIB_GZIP_INFLATING:
default: default:
@ -555,38 +568,37 @@ static CURLcode gzip_unencode_write(struct connectdata *conn,
} }
/* We've parsed the header, now uncompress the data */ /* We've parsed the header, now uncompress the data */
return inflate_stream(conn, writer, ZLIB_GZIP_INFLATING); return inflate_stream(data, writer, ZLIB_GZIP_INFLATING);
#endif #endif
} }
static void gzip_close_writer(struct connectdata *conn, static void gzip_close_writer(struct Curl_easy *data,
contenc_writer *writer) struct contenc_writer *writer)
{ {
zlib_params *zp = (zlib_params *) &writer->params; struct zlib_writer *zp = (struct zlib_writer *) writer;
z_stream *z = &zp->z; /* zlib state structure */ z_stream *z = &zp->z; /* zlib state structure */
exit_zlib(conn, z, &zp->zlib_init, CURLE_OK); exit_zlib(data, z, &zp->zlib_init, CURLE_OK);
} }
static const content_encoding gzip_encoding = { static const struct content_encoding gzip_encoding = {
"gzip", "gzip",
"x-gzip", "x-gzip",
gzip_init_writer, gzip_init_writer,
gzip_unencode_write, gzip_unencode_write,
gzip_close_writer, gzip_close_writer,
sizeof(zlib_params) sizeof(struct zlib_writer)
}; };
#endif /* HAVE_LIBZ */ #endif /* HAVE_LIBZ */
#ifdef HAVE_BROTLI #ifdef HAVE_BROTLI
/* Brotli writer. */
/* Writer parameters. */ struct brotli_writer {
typedef struct { struct contenc_writer super;
BrotliDecoderState *br; /* State structure for brotli. */ BrotliDecoderState *br; /* State structure for brotli. */
} brotli_params; };
static CURLcode brotli_map_error(BrotliDecoderErrorCode be) static CURLcode brotli_map_error(BrotliDecoderErrorCode be)
{ {
@ -626,12 +638,11 @@ static CURLcode brotli_map_error(BrotliDecoderErrorCode be)
return CURLE_WRITE_ERROR; return CURLE_WRITE_ERROR;
} }
static CURLcode brotli_init_writer(struct connectdata *conn, static CURLcode brotli_init_writer(struct Curl_easy *data,
contenc_writer *writer) struct contenc_writer *writer)
{ {
brotli_params *bp = (brotli_params *) &writer->params; struct brotli_writer *bp = (struct brotli_writer *) writer;
(void) data;
(void) conn;
if(!writer->downstream) if(!writer->downstream)
return CURLE_WRITE_ERROR; return CURLE_WRITE_ERROR;
@ -640,11 +651,11 @@ static CURLcode brotli_init_writer(struct connectdata *conn,
return bp->br? CURLE_OK: CURLE_OUT_OF_MEMORY; return bp->br? CURLE_OK: CURLE_OUT_OF_MEMORY;
} }
static CURLcode brotli_unencode_write(struct connectdata *conn, static CURLcode brotli_unencode_write(struct Curl_easy *data,
contenc_writer *writer, struct contenc_writer *writer,
const char *buf, size_t nbytes) const char *buf, size_t nbytes)
{ {
brotli_params *bp = (brotli_params *) &writer->params; struct brotli_writer *bp = (struct brotli_writer *) writer;
const uint8_t *src = (const uint8_t *) buf; const uint8_t *src = (const uint8_t *) buf;
char *decomp; char *decomp;
uint8_t *dst; uint8_t *dst;
@ -665,7 +676,7 @@ static CURLcode brotli_unencode_write(struct connectdata *conn,
dstleft = DSIZ; dstleft = DSIZ;
r = BrotliDecoderDecompressStream(bp->br, r = BrotliDecoderDecompressStream(bp->br,
&nbytes, &src, &dstleft, &dst, NULL); &nbytes, &src, &dstleft, &dst, NULL);
result = Curl_unencode_write(conn, writer->downstream, result = Curl_unencode_write(data, writer->downstream,
decomp, DSIZ - dstleft); decomp, DSIZ - dstleft);
if(result) if(result)
break; break;
@ -688,12 +699,12 @@ static CURLcode brotli_unencode_write(struct connectdata *conn,
return result; return result;
} }
static void brotli_close_writer(struct connectdata *conn, static void brotli_close_writer(struct Curl_easy *data,
contenc_writer *writer) struct contenc_writer *writer)
{ {
brotli_params *bp = (brotli_params *) &writer->params; struct brotli_writer *bp = (struct brotli_writer *) writer;
(void) conn; (void) data;
if(bp->br) { if(bp->br) {
BrotliDecoderDestroyInstance(bp->br); BrotliDecoderDestroyInstance(bp->br);
@ -701,51 +712,143 @@ static void brotli_close_writer(struct connectdata *conn,
} }
} }
static const content_encoding brotli_encoding = { static const struct content_encoding brotli_encoding = {
"br", "br",
NULL, NULL,
brotli_init_writer, brotli_init_writer,
brotli_unencode_write, brotli_unencode_write,
brotli_close_writer, brotli_close_writer,
sizeof(brotli_params) sizeof(struct brotli_writer)
};
#endif
#ifdef HAVE_ZSTD
/* Zstd writer. */
struct zstd_writer {
struct contenc_writer super;
ZSTD_DStream *zds; /* State structure for zstd. */
void *decomp;
};
static CURLcode zstd_init_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
struct zstd_writer *zp = (struct zstd_writer *) writer;
(void)data;
if(!writer->downstream)
return CURLE_WRITE_ERROR;
zp->zds = ZSTD_createDStream();
zp->decomp = NULL;
return zp->zds ? CURLE_OK : CURLE_OUT_OF_MEMORY;
}
static CURLcode zstd_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
CURLcode result = CURLE_OK;
struct zstd_writer *zp = (struct zstd_writer *) writer;
ZSTD_inBuffer in;
ZSTD_outBuffer out;
size_t errorCode;
if(!zp->decomp) {
zp->decomp = malloc(DSIZ);
if(!zp->decomp)
return CURLE_OUT_OF_MEMORY;
}
in.pos = 0;
in.src = buf;
in.size = nbytes;
for(;;) {
out.pos = 0;
out.dst = zp->decomp;
out.size = DSIZ;
errorCode = ZSTD_decompressStream(zp->zds, &out, &in);
if(ZSTD_isError(errorCode)) {
return CURLE_BAD_CONTENT_ENCODING;
}
if(out.pos > 0) {
result = Curl_unencode_write(data, writer->downstream,
zp->decomp, out.pos);
if(result)
break;
}
if((in.pos == nbytes) && (out.pos < out.size))
break;
}
return result;
}
static void zstd_close_writer(struct Curl_easy *data,
struct contenc_writer *writer)
{
struct zstd_writer *zp = (struct zstd_writer *) writer;
(void)data;
if(zp->decomp) {
free(zp->decomp);
zp->decomp = NULL;
}
if(zp->zds) {
ZSTD_freeDStream(zp->zds);
zp->zds = NULL;
}
}
static const struct content_encoding zstd_encoding = {
"zstd",
NULL,
zstd_init_writer,
zstd_unencode_write,
zstd_close_writer,
sizeof(struct zstd_writer)
}; };
#endif #endif
/* Identity handler. */ /* Identity handler. */
static CURLcode identity_init_writer(struct connectdata *conn, static CURLcode identity_init_writer(struct Curl_easy *data,
contenc_writer *writer) struct contenc_writer *writer)
{ {
(void) conn; (void) data;
return writer->downstream? CURLE_OK: CURLE_WRITE_ERROR; return writer->downstream? CURLE_OK: CURLE_WRITE_ERROR;
} }
static CURLcode identity_unencode_write(struct connectdata *conn, static CURLcode identity_unencode_write(struct Curl_easy *data,
contenc_writer *writer, struct contenc_writer *writer,
const char *buf, size_t nbytes) const char *buf, size_t nbytes)
{ {
return Curl_unencode_write(conn, writer->downstream, buf, nbytes); return Curl_unencode_write(data, writer->downstream, buf, nbytes);
} }
static void identity_close_writer(struct connectdata *conn, static void identity_close_writer(struct Curl_easy *data,
contenc_writer *writer) struct contenc_writer *writer)
{ {
(void) conn; (void) data;
(void) writer; (void) writer;
} }
static const content_encoding identity_encoding = { static const struct content_encoding identity_encoding = {
"identity", "identity",
"none", "none",
identity_init_writer, identity_init_writer,
identity_unencode_write, identity_unencode_write,
identity_close_writer, identity_close_writer,
0 sizeof(struct contenc_writer)
}; };
/* supported content encodings table. */ /* supported content encodings table. */
static const content_encoding * const encodings[] = { static const struct content_encoding * const encodings[] = {
&identity_encoding, &identity_encoding,
#ifdef HAVE_LIBZ #ifdef HAVE_LIBZ
&deflate_encoding, &deflate_encoding,
@ -753,6 +856,9 @@ static const content_encoding * const encodings[] = {
#endif #endif
#ifdef HAVE_BROTLI #ifdef HAVE_BROTLI
&brotli_encoding, &brotli_encoding,
#endif
#ifdef HAVE_ZSTD
&zstd_encoding,
#endif #endif
NULL NULL
}; };
@ -762,8 +868,8 @@ static const content_encoding * const encodings[] = {
char *Curl_all_content_encodings(void) char *Curl_all_content_encodings(void)
{ {
size_t len = 0; size_t len = 0;
const content_encoding * const *cep; const struct content_encoding * const *cep;
const content_encoding *ce; const struct content_encoding *ce;
char *ace; char *ace;
for(cep = encodings; *cep; cep++) { for(cep = encodings; *cep; cep++) {
@ -795,18 +901,17 @@ char *Curl_all_content_encodings(void)
/* Real client writer: no downstream. */ /* Real client writer: no downstream. */
static CURLcode client_init_writer(struct connectdata *conn, static CURLcode client_init_writer(struct Curl_easy *data,
contenc_writer *writer) struct contenc_writer *writer)
{ {
(void) conn; (void) data;
return writer->downstream? CURLE_WRITE_ERROR: CURLE_OK; return writer->downstream? CURLE_WRITE_ERROR: CURLE_OK;
} }
static CURLcode client_unencode_write(struct connectdata *conn, static CURLcode client_unencode_write(struct Curl_easy *data,
contenc_writer *writer, struct contenc_writer *writer,
const char *buf, size_t nbytes) const char *buf, size_t nbytes)
{ {
struct Curl_easy *data = conn->data;
struct SingleRequest *k = &data->req; struct SingleRequest *k = &data->req;
(void) writer; (void) writer;
@ -814,36 +919,36 @@ static CURLcode client_unencode_write(struct connectdata *conn,
if(!nbytes || k->ignorebody) if(!nbytes || k->ignorebody)
return CURLE_OK; return CURLE_OK;
return Curl_client_write(conn, CLIENTWRITE_BODY, (char *) buf, nbytes); return Curl_client_write(data, CLIENTWRITE_BODY, (char *) buf, nbytes);
} }
static void client_close_writer(struct connectdata *conn, static void client_close_writer(struct Curl_easy *data,
contenc_writer *writer) struct contenc_writer *writer)
{ {
(void) conn; (void) data;
(void) writer; (void) writer;
} }
static const content_encoding client_encoding = { static const struct content_encoding client_encoding = {
NULL, NULL,
NULL, NULL,
client_init_writer, client_init_writer,
client_unencode_write, client_unencode_write,
client_close_writer, client_close_writer,
0 sizeof(struct contenc_writer)
}; };
/* Deferred error dummy writer. */ /* Deferred error dummy writer. */
static CURLcode error_init_writer(struct connectdata *conn, static CURLcode error_init_writer(struct Curl_easy *data,
contenc_writer *writer) struct contenc_writer *writer)
{ {
(void) conn; (void) data;
return writer->downstream? CURLE_OK: CURLE_WRITE_ERROR; return writer->downstream? CURLE_OK: CURLE_WRITE_ERROR;
} }
static CURLcode error_unencode_write(struct connectdata *conn, static CURLcode error_unencode_write(struct Curl_easy *data,
contenc_writer *writer, struct contenc_writer *writer,
const char *buf, size_t nbytes) const char *buf, size_t nbytes)
{ {
char *all = Curl_all_content_encodings(); char *all = Curl_all_content_encodings();
@ -854,40 +959,45 @@ static CURLcode error_unencode_write(struct connectdata *conn,
if(!all) if(!all)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
failf(conn->data, "Unrecognized content encoding type. " failf(data, "Unrecognized content encoding type. "
"libcurl understands %s content encodings.", all); "libcurl understands %s content encodings.", all);
free(all); free(all);
return CURLE_BAD_CONTENT_ENCODING; return CURLE_BAD_CONTENT_ENCODING;
} }
static void error_close_writer(struct connectdata *conn, static void error_close_writer(struct Curl_easy *data,
contenc_writer *writer) struct contenc_writer *writer)
{ {
(void) conn; (void) data;
(void) writer; (void) writer;
} }
static const content_encoding error_encoding = { static const struct content_encoding error_encoding = {
NULL, NULL,
NULL, NULL,
error_init_writer, error_init_writer,
error_unencode_write, error_unencode_write,
error_close_writer, error_close_writer,
0 sizeof(struct contenc_writer)
}; };
/* Create an unencoding writer stage using the given handler. */ /* Create an unencoding writer stage using the given handler. */
static contenc_writer *new_unencoding_writer(struct connectdata *conn, static struct contenc_writer *
const content_encoding *handler, new_unencoding_writer(struct Curl_easy *data,
contenc_writer *downstream) const struct content_encoding *handler,
struct contenc_writer *downstream,
int order)
{ {
size_t sz = offsetof(contenc_writer, params) + handler->paramsize; struct contenc_writer *writer;
contenc_writer *writer = (contenc_writer *) calloc(1, sz);
DEBUGASSERT(handler->writersize >= sizeof(struct contenc_writer));
writer = (struct contenc_writer *) calloc(1, handler->writersize);
if(writer) { if(writer) {
writer->handler = handler; writer->handler = handler;
writer->downstream = downstream; writer->downstream = downstream;
if(handler->init_writer(conn, writer)) { writer->order = order;
if(handler->init_writer(data, writer)) {
free(writer); free(writer);
writer = NULL; writer = NULL;
} }
@ -896,37 +1006,39 @@ static contenc_writer *new_unencoding_writer(struct connectdata *conn,
return writer; return writer;
} }
/* Write data using an unencoding writer stack. */ /* Write data using an unencoding writer stack. "nbytes" is not
CURLcode Curl_unencode_write(struct connectdata *conn, contenc_writer *writer, allowed to be 0. */
CURLcode Curl_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes) const char *buf, size_t nbytes)
{ {
if(!nbytes) if(!nbytes)
return CURLE_OK; return CURLE_OK;
return writer->handler->unencode_write(conn, writer, buf, nbytes); return writer->handler->unencode_write(data, writer, buf, nbytes);
} }
/* Close and clean-up the connection's writer stack. */ /* Close and clean-up the connection's writer stack. */
void Curl_unencode_cleanup(struct connectdata *conn) void Curl_unencode_cleanup(struct Curl_easy *data)
{ {
struct Curl_easy *data = conn->data;
struct SingleRequest *k = &data->req; struct SingleRequest *k = &data->req;
contenc_writer *writer = k->writer_stack; struct contenc_writer *writer = k->writer_stack;
while(writer) { while(writer) {
k->writer_stack = writer->downstream; k->writer_stack = writer->downstream;
writer->handler->close_writer(conn, writer); writer->handler->close_writer(data, writer);
free(writer); free(writer);
writer = k->writer_stack; writer = k->writer_stack;
} }
} }
/* Find the content encoding by name. */ /* Find the content encoding by name. */
static const content_encoding *find_encoding(const char *name, size_t len) static const struct content_encoding *find_encoding(const char *name,
size_t len)
{ {
const content_encoding * const *cep; const struct content_encoding * const *cep;
for(cep = encodings; *cep; cep++) { for(cep = encodings; *cep; cep++) {
const content_encoding *ce = *cep; const struct content_encoding *ce = *cep;
if((strncasecompare(name, ce->name, len) && !ce->name[len]) || if((strncasecompare(name, ce->name, len) && !ce->name[len]) ||
(ce->alias && strncasecompare(name, ce->alias, len) && !ce->alias[len])) (ce->alias && strncasecompare(name, ce->alias, len) && !ce->alias[len]))
return ce; return ce;
@ -934,20 +1046,23 @@ static const content_encoding *find_encoding(const char *name, size_t len)
return NULL; return NULL;
} }
/* allow no more than 5 "chained" compression steps */
#define MAX_ENCODE_STACK 5
/* Set-up the unencoding stack from the Content-Encoding header value. /* Set-up the unencoding stack from the Content-Encoding header value.
* See RFC 7231 section 3.1.2.2. */ * See RFC 7231 section 3.1.2.2. */
CURLcode Curl_build_unencoding_stack(struct connectdata *conn, CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
const char *enclist, int maybechunked) const char *enclist, int is_transfer)
{ {
struct Curl_easy *data = conn->data;
struct SingleRequest *k = &data->req; struct SingleRequest *k = &data->req;
unsigned int order = is_transfer? 2: 1;
do { do {
const char *name; const char *name;
size_t namelen; size_t namelen;
/* Parse a single encoding name. */ /* Parse a single encoding name. */
while(ISSPACE(*enclist) || *enclist == ',') while(ISBLANK(*enclist) || *enclist == ',')
enclist++; enclist++;
name = enclist; name = enclist;
@ -957,16 +1072,17 @@ CURLcode Curl_build_unencoding_stack(struct connectdata *conn,
namelen = enclist - name + 1; namelen = enclist - name + 1;
/* Special case: chunked encoding is handled at the reader level. */ /* Special case: chunked encoding is handled at the reader level. */
if(maybechunked && namelen == 7 && strncasecompare(name, "chunked", 7)) { if(is_transfer && namelen == 7 && strncasecompare(name, "chunked", 7)) {
k->chunk = TRUE; /* chunks coming our way. */ k->chunk = TRUE; /* chunks coming our way. */
Curl_httpchunk_init(conn); /* init our chunky engine. */ Curl_httpchunk_init(data); /* init our chunky engine. */
} }
else if(namelen) { else if(namelen) {
const content_encoding *encoding = find_encoding(name, namelen); const struct content_encoding *encoding = find_encoding(name, namelen);
contenc_writer *writer; struct contenc_writer *writer;
if(!k->writer_stack) { if(!k->writer_stack) {
k->writer_stack = new_unencoding_writer(conn, &client_encoding, NULL); k->writer_stack = new_unencoding_writer(data, &client_encoding,
NULL, 0);
if(!k->writer_stack) if(!k->writer_stack)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
@ -975,11 +1091,29 @@ CURLcode Curl_build_unencoding_stack(struct connectdata *conn,
if(!encoding) if(!encoding)
encoding = &error_encoding; /* Defer error at stack use. */ encoding = &error_encoding; /* Defer error at stack use. */
if(k->writer_stack_depth++ >= MAX_ENCODE_STACK) {
failf(data, "Reject response due to more than %u content encodings",
MAX_ENCODE_STACK);
return CURLE_BAD_CONTENT_ENCODING;
}
/* Stack the unencoding stage. */ /* Stack the unencoding stage. */
writer = new_unencoding_writer(conn, encoding, k->writer_stack); if(order >= k->writer_stack->order) {
if(!writer) writer = new_unencoding_writer(data, encoding,
return CURLE_OUT_OF_MEMORY; k->writer_stack, order);
k->writer_stack = writer; if(!writer)
return CURLE_OUT_OF_MEMORY;
k->writer_stack = writer;
}
else {
struct contenc_writer *w = k->writer_stack;
while(w->downstream && order < w->downstream->order)
w = w->downstream;
writer = new_unencoding_writer(data, encoding,
w->downstream, order);
if(!writer)
return CURLE_OUT_OF_MEMORY;
w->downstream = writer;
}
} }
} while(*enclist); } while(*enclist);
@ -988,28 +1122,29 @@ CURLcode Curl_build_unencoding_stack(struct connectdata *conn,
#else #else
/* Stubs for builds without HTTP. */ /* Stubs for builds without HTTP. */
CURLcode Curl_build_unencoding_stack(struct connectdata *conn, CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
const char *enclist, int maybechunked) const char *enclist, int is_transfer)
{ {
(void) conn; (void) data;
(void) enclist; (void) enclist;
(void) maybechunked; (void) is_transfer;
return CURLE_NOT_BUILT_IN; return CURLE_NOT_BUILT_IN;
} }
CURLcode Curl_unencode_write(struct connectdata *conn, contenc_writer *writer, CURLcode Curl_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes) const char *buf, size_t nbytes)
{ {
(void) conn; (void) data;
(void) writer; (void) writer;
(void) buf; (void) buf;
(void) nbytes; (void) nbytes;
return CURLE_NOT_BUILT_IN; return CURLE_NOT_BUILT_IN;
} }
void Curl_unencode_cleanup(struct connectdata *conn) void Curl_unencode_cleanup(struct Curl_easy *data)
{ {
(void) conn; (void) data;
} }
char *Curl_all_content_encodings(void) char *Curl_all_content_encodings(void)

View file

@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -20,36 +20,38 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#include "curl_setup.h" #include "curl_setup.h"
/* Decoding writer. */ struct contenc_writer {
typedef struct contenc_writer_s contenc_writer; const struct content_encoding *handler; /* Encoding handler. */
typedef struct content_encoding_s content_encoding; struct contenc_writer *downstream; /* Downstream writer. */
unsigned int order; /* Ordering within writer stack. */
struct contenc_writer_s {
const content_encoding *handler; /* Encoding handler. */
contenc_writer *downstream; /* Downstream writer. */
void *params; /* Encoding-specific storage (variable length). */
}; };
/* Content encoding writer. */ /* Content encoding writer. */
struct content_encoding_s { struct content_encoding {
const char *name; /* Encoding name. */ const char *name; /* Encoding name. */
const char *alias; /* Encoding name alias. */ const char *alias; /* Encoding name alias. */
CURLcode (*init_writer)(struct connectdata *conn, contenc_writer *writer); CURLcode (*init_writer)(struct Curl_easy *data,
CURLcode (*unencode_write)(struct connectdata *conn, contenc_writer *writer, struct contenc_writer *writer);
CURLcode (*unencode_write)(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes); const char *buf, size_t nbytes);
void (*close_writer)(struct connectdata *conn, contenc_writer *writer); void (*close_writer)(struct Curl_easy *data,
size_t paramsize; struct contenc_writer *writer);
size_t writersize;
}; };
CURLcode Curl_build_unencoding_stack(struct connectdata *conn, CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
const char *enclist, int maybechunked); const char *enclist, int is_transfer);
CURLcode Curl_unencode_write(struct connectdata *conn, contenc_writer *writer, CURLcode Curl_unencode_write(struct Curl_easy *data,
struct contenc_writer *writer,
const char *buf, size_t nbytes); const char *buf, size_t nbytes);
void Curl_unencode_cleanup(struct connectdata *conn); void Curl_unencode_cleanup(struct Curl_easy *data);
char *Curl_all_content_encodings(void); char *Curl_all_content_encodings(void);
#endif /* HEADER_CURL_CONTENT_ENCODING_H */ #endif /* HEADER_CURL_CONTENT_ENCODING_H */

File diff suppressed because it is too large Load diff

View file

@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#include "curl_setup.h" #include "curl_setup.h"
@ -34,12 +36,12 @@ struct Cookie {
char *domain; /* domain = <this> */ char *domain; /* domain = <this> */
curl_off_t expires; /* expires = <this> */ curl_off_t expires; /* expires = <this> */
char *expirestr; /* the plain text version */ char *expirestr; /* the plain text version */
bool tailmatch; /* whether we do tail-matching of the domain name */
/* RFC 2109 keywords. Version=1 means 2109-compliant cookie sending */ /* RFC 2109 keywords. Version=1 means 2109-compliant cookie sending */
char *version; /* Version = <value> */ char *version; /* Version = <value> */
char *maxage; /* Max-Age = <value> */ char *maxage; /* Max-Age = <value> */
bool tailmatch; /* whether we do tail-matching of the domain name */
bool secure; /* whether the 'secure' keyword was used */ bool secure; /* whether the 'secure' keyword was used */
bool livecookie; /* updated from a server, not a stored file */ bool livecookie; /* updated from a server, not a stored file */
bool httponly; /* true if the httponly directive is present */ bool httponly; /* true if the httponly directive is present */
@ -61,10 +63,11 @@ struct CookieInfo {
struct Cookie *cookies[COOKIE_HASH_SIZE]; struct Cookie *cookies[COOKIE_HASH_SIZE];
char *filename; /* file we read from/write to */ char *filename; /* file we read from/write to */
bool running; /* state info, for cookie adding information */
long numcookies; /* number of cookies in the "jar" */ long numcookies; /* number of cookies in the "jar" */
bool running; /* state info, for cookie adding information */
bool newsession; /* new session, discard session cookies on load */ bool newsession; /* new session, discard session cookies on load */
int lastct; /* last creation-time used in the jar */ int lastct; /* last creation-time used in the jar */
curl_off_t next_expiration; /* the next time at which expiration happens */
}; };
/* This is the maximum line length we accept for a cookie line. RFC 2109 /* This is the maximum line length we accept for a cookie line. RFC 2109
@ -80,10 +83,26 @@ struct CookieInfo {
*/ */
#define MAX_COOKIE_LINE 5000 #define MAX_COOKIE_LINE 5000
/* This is the maximum length of a cookie name or content we deal with: */ /* Maximum length of an incoming cookie name or content we deal with. Longer
cookies are ignored. */
#define MAX_NAME 4096 #define MAX_NAME 4096
#define MAX_NAME_TXT "4095" #define MAX_NAME_TXT "4095"
/* Maximum size for an outgoing cookie line libcurl will use in an http
request. This is the default maximum length used in some versions of Apache
httpd. */
#define MAX_COOKIE_HEADER_LEN 8190
/* Maximum number of cookies libcurl will send in a single request, even if
there might be more cookies that match. One reason to cap the number is to
keep the maximum HTTP request within the maximum allowed size. */
#define MAX_COOKIE_SEND_AMOUNT 150
/* Maximum number of Set-Cookie: lines accepted in a single response. If more
such header lines are received, they are ignored. This value must be less
than 256 since an unsigned char is used to count. */
#define MAX_SET_COOKIE_AMOUNT 50
struct Curl_easy; struct Curl_easy;
/* /*
* Add a cookie to the internal list of cookies. The domain and path arguments * Add a cookie to the internal list of cookies. The domain and path arguments
@ -91,13 +110,14 @@ struct Curl_easy;
*/ */
struct Cookie *Curl_cookie_add(struct Curl_easy *data, struct Cookie *Curl_cookie_add(struct Curl_easy *data,
struct CookieInfo *, bool header, bool noexpiry, struct CookieInfo *c, bool header,
char *lineptr, bool noexpiry, char *lineptr,
const char *domain, const char *path, const char *domain, const char *path,
bool secure); bool secure);
struct Cookie *Curl_cookie_getlist(struct CookieInfo *, const char *, struct Cookie *Curl_cookie_getlist(struct Curl_easy *data,
const char *, bool); struct CookieInfo *c, const char *host,
const char *path, bool secure);
void Curl_cookie_freelist(struct Cookie *cookies); void Curl_cookie_freelist(struct Cookie *cookies);
void Curl_cookie_clearall(struct CookieInfo *cookies); void Curl_cookie_clearall(struct CookieInfo *cookies);
void Curl_cookie_clearsess(struct CookieInfo *cookies); void Curl_cookie_clearsess(struct CookieInfo *cookies);
@ -109,10 +129,11 @@ void Curl_cookie_clearsess(struct CookieInfo *cookies);
#define Curl_cookie_cleanup(x) Curl_nop_stmt #define Curl_cookie_cleanup(x) Curl_nop_stmt
#define Curl_flush_cookies(x,y) Curl_nop_stmt #define Curl_flush_cookies(x,y) Curl_nop_stmt
#else #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 *); void Curl_cookie_cleanup(struct CookieInfo *c);
struct CookieInfo *Curl_cookie_init(struct Curl_easy *data, struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
const char *, struct CookieInfo *, bool); const char *file, struct CookieInfo *inc,
bool newsession);
struct curl_slist *Curl_cookie_list(struct Curl_easy *data); struct curl_slist *Curl_cookie_list(struct Curl_easy *data);
void Curl_cookie_loadfiles(struct Curl_easy *data); void Curl_cookie_loadfiles(struct Curl_easy *data);
#endif #endif

View file

@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#include "curl_setup.h" #include "curl_setup.h"
@ -45,15 +47,6 @@
# include <inet.h> # include <inet.h>
#endif #endif
#if defined(NETWARE) && defined(__NOVELL_LIBC__)
# undef in_addr_t
# define in_addr_t unsigned long
#endif
#if defined(WIN32) && defined(USE_UNIX_SOCKETS)
#include <afunix.h>
#endif
#include <stddef.h> #include <stddef.h>
#include "curl_addrinfo.h" #include "curl_addrinfo.h"
@ -82,16 +75,13 @@
#endif #endif
void void
Curl_freeaddrinfo(Curl_addrinfo *cahead) Curl_freeaddrinfo(struct Curl_addrinfo *cahead)
{ {
Curl_addrinfo *vqualifier canext; struct Curl_addrinfo *vqualifier canext;
Curl_addrinfo *ca; struct Curl_addrinfo *ca;
for(ca = cahead; ca != NULL; ca = canext) { for(ca = cahead; ca; ca = canext) {
free(ca->ai_addr);
free(ca->ai_canonname);
canext = ca->ai_next; canext = ca->ai_next;
free(ca); free(ca);
} }
} }
@ -116,13 +106,13 @@ int
Curl_getaddrinfo_ex(const char *nodename, Curl_getaddrinfo_ex(const char *nodename,
const char *servname, const char *servname,
const struct addrinfo *hints, const struct addrinfo *hints,
Curl_addrinfo **result) struct Curl_addrinfo **result)
{ {
const struct addrinfo *ai; const struct addrinfo *ai;
struct addrinfo *aihead; struct addrinfo *aihead;
Curl_addrinfo *cafirst = NULL; struct Curl_addrinfo *cafirst = NULL;
Curl_addrinfo *calast = NULL; struct Curl_addrinfo *calast = NULL;
Curl_addrinfo *ca; struct Curl_addrinfo *ca;
size_t ss_size; size_t ss_size;
int error; int error;
@ -135,7 +125,7 @@ Curl_getaddrinfo_ex(const char *nodename,
/* traverse the addrinfo list */ /* traverse the addrinfo list */
for(ai = aihead; ai != NULL; ai = ai->ai_next) { for(ai = aihead; ai != NULL; ai = ai->ai_next) {
size_t namelen = ai->ai_canonname ? strlen(ai->ai_canonname) + 1 : 0;
/* ignore elements with unsupported address family, */ /* ignore elements with unsupported address family, */
/* settle family-specific sockaddr structure size. */ /* settle family-specific sockaddr structure size. */
if(ai->ai_family == AF_INET) if(ai->ai_family == AF_INET)
@ -148,14 +138,14 @@ Curl_getaddrinfo_ex(const char *nodename,
continue; continue;
/* ignore elements without required address info */ /* ignore elements without required address info */
if((ai->ai_addr == NULL) || !(ai->ai_addrlen > 0)) if(!ai->ai_addr || !(ai->ai_addrlen > 0))
continue; continue;
/* ignore elements with bogus address size */ /* ignore elements with bogus address size */
if((size_t)ai->ai_addrlen < ss_size) if((size_t)ai->ai_addrlen < ss_size)
continue; continue;
ca = malloc(sizeof(Curl_addrinfo)); ca = malloc(sizeof(struct Curl_addrinfo) + ss_size + namelen);
if(!ca) { if(!ca) {
error = EAI_MEMORY; error = EAI_MEMORY;
break; break;
@ -173,22 +163,12 @@ Curl_getaddrinfo_ex(const char *nodename,
ca->ai_canonname = NULL; ca->ai_canonname = NULL;
ca->ai_next = NULL; ca->ai_next = NULL;
ca->ai_addr = malloc(ss_size); ca->ai_addr = (void *)((char *)ca + sizeof(struct Curl_addrinfo));
if(!ca->ai_addr) {
error = EAI_MEMORY;
free(ca);
break;
}
memcpy(ca->ai_addr, ai->ai_addr, ss_size); memcpy(ca->ai_addr, ai->ai_addr, ss_size);
if(ai->ai_canonname != NULL) { if(namelen) {
ca->ai_canonname = strdup(ai->ai_canonname); ca->ai_canonname = (void *)((char *)ca->ai_addr + ss_size);
if(!ca->ai_canonname) { memcpy(ca->ai_canonname, ai->ai_canonname, namelen);
error = EAI_MEMORY;
free(ca->ai_addr);
free(ca);
break;
}
} }
/* if the return list is empty, this becomes the first element */ /* if the return list is empty, this becomes the first element */
@ -256,7 +236,6 @@ Curl_getaddrinfo_ex(const char *nodename,
* struct sockaddr *ai_addr; * struct sockaddr *ai_addr;
* struct Curl_addrinfo *ai_next; * struct Curl_addrinfo *ai_next;
* }; * };
* typedef struct Curl_addrinfo Curl_addrinfo;
* *
* hostent defined in <netdb.h> * hostent defined in <netdb.h>
* *
@ -273,12 +252,12 @@ Curl_getaddrinfo_ex(const char *nodename,
* #define h_addr h_addr_list[0] * #define h_addr h_addr_list[0]
*/ */
Curl_addrinfo * struct Curl_addrinfo *
Curl_he2ai(const struct hostent *he, int port) Curl_he2ai(const struct hostent *he, int port)
{ {
Curl_addrinfo *ai; struct Curl_addrinfo *ai;
Curl_addrinfo *prevai = NULL; struct Curl_addrinfo *prevai = NULL;
Curl_addrinfo *firstai = NULL; struct Curl_addrinfo *firstai = NULL;
struct sockaddr_in *addr; struct sockaddr_in *addr;
#ifdef ENABLE_IPV6 #ifdef ENABLE_IPV6
struct sockaddr_in6 *addr6; struct sockaddr_in6 *addr6;
@ -294,8 +273,8 @@ Curl_he2ai(const struct hostent *he, int port)
DEBUGASSERT((he->h_name != NULL) && (he->h_addr_list != NULL)); DEBUGASSERT((he->h_name != NULL) && (he->h_addr_list != NULL));
for(i = 0; (curr = he->h_addr_list[i]) != NULL; i++) { for(i = 0; (curr = he->h_addr_list[i]) != NULL; i++) {
size_t ss_size; size_t ss_size;
size_t namelen = strlen(he->h_name) + 1; /* include null-terminatior */
#ifdef ENABLE_IPV6 #ifdef ENABLE_IPV6
if(he->h_addrtype == AF_INET6) if(he->h_addrtype == AF_INET6)
ss_size = sizeof(struct sockaddr_in6); ss_size = sizeof(struct sockaddr_in6);
@ -303,24 +282,17 @@ Curl_he2ai(const struct hostent *he, int port)
#endif #endif
ss_size = sizeof(struct sockaddr_in); ss_size = sizeof(struct sockaddr_in);
ai = calloc(1, sizeof(Curl_addrinfo)); /* allocate memory to hold the struct, the address and the name */
ai = calloc(1, sizeof(struct Curl_addrinfo) + ss_size + namelen);
if(!ai) { if(!ai) {
result = CURLE_OUT_OF_MEMORY; result = CURLE_OUT_OF_MEMORY;
break; break;
} }
ai->ai_canonname = strdup(he->h_name); /* put the address after the struct */
if(!ai->ai_canonname) { ai->ai_addr = (void *)((char *)ai + sizeof(struct Curl_addrinfo));
result = CURLE_OUT_OF_MEMORY; /* then put the name after the address */
free(ai); ai->ai_canonname = (char *)ai->ai_addr + ss_size;
break; memcpy(ai->ai_canonname, he->h_name, namelen);
}
ai->ai_addr = calloc(1, ss_size);
if(!ai->ai_addr) {
result = CURLE_OUT_OF_MEMORY;
free(ai->ai_canonname);
free(ai);
break;
}
if(!firstai) if(!firstai)
/* store the pointer we want to return from this function */ /* store the pointer we want to return from this function */
@ -393,10 +365,10 @@ struct namebuff {
* given address/host * given address/host
*/ */
Curl_addrinfo * struct Curl_addrinfo *
Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port) Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port)
{ {
Curl_addrinfo *ai; struct Curl_addrinfo *ai;
#if defined(__VMS) && \ #if defined(__VMS) && \
defined(__INITIAL_POINTER_SIZE) && (__INITIAL_POINTER_SIZE == 64) defined(__INITIAL_POINTER_SIZE) && (__INITIAL_POINTER_SIZE == 64)
@ -469,7 +441,7 @@ Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port)
* Given an IPv4 or IPv6 dotted string address, this converts it to a proper * Given an IPv4 or IPv6 dotted string address, this converts it to a proper
* allocated Curl_addrinfo struct and returns it. * allocated Curl_addrinfo struct and returns it.
*/ */
Curl_addrinfo *Curl_str2addr(char *address, int port) struct Curl_addrinfo *Curl_str2addr(char *address, int port)
{ {
struct in_addr in; struct in_addr in;
if(Curl_inet_pton(AF_INET, address, &in) > 0) if(Curl_inet_pton(AF_INET, address, &in) > 0)
@ -492,22 +464,19 @@ Curl_addrinfo *Curl_str2addr(char *address, int port)
* struct initialized with this path. * struct initialized with this path.
* Set '*longpath' to TRUE if the error is a too long path. * Set '*longpath' to TRUE if the error is a too long path.
*/ */
Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract) struct Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath,
bool abstract)
{ {
Curl_addrinfo *ai; struct Curl_addrinfo *ai;
struct sockaddr_un *sa_un; struct sockaddr_un *sa_un;
size_t path_len; size_t path_len;
*longpath = FALSE; *longpath = FALSE;
ai = calloc(1, sizeof(Curl_addrinfo)); ai = calloc(1, sizeof(struct Curl_addrinfo) + sizeof(struct sockaddr_un));
if(!ai) if(!ai)
return NULL; return NULL;
ai->ai_addr = calloc(1, sizeof(struct sockaddr_un)); ai->ai_addr = (void *)((char *)ai + sizeof(struct Curl_addrinfo));
if(!ai->ai_addr) {
free(ai);
return NULL;
}
sa_un = (void *) ai->ai_addr; sa_un = (void *) ai->ai_addr;
sa_un->sun_family = AF_UNIX; sa_un->sun_family = AF_UNIX;
@ -515,7 +484,6 @@ Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract)
/* sun_path must be able to store the NUL-terminated path */ /* sun_path must be able to store the NUL-terminated path */
path_len = strlen(path) + 1; path_len = strlen(path) + 1;
if(path_len > sizeof(sa_un->sun_path)) { if(path_len > sizeof(sa_un->sun_path)) {
free(ai->ai_addr);
free(ai); free(ai);
*longpath = TRUE; *longpath = TRUE;
return NULL; return NULL;
@ -598,9 +566,9 @@ curl_dbg_getaddrinfo(const char *hostname,
* Work-arounds the sin6_port is always zero bug on iOS 9.3.2 and Mac OS X * Work-arounds the sin6_port is always zero bug on iOS 9.3.2 and Mac OS X
* 10.11.5. * 10.11.5.
*/ */
void Curl_addrinfo_set_port(Curl_addrinfo *addrinfo, int port) void Curl_addrinfo_set_port(struct Curl_addrinfo *addrinfo, int port)
{ {
Curl_addrinfo *ca; struct Curl_addrinfo *ca;
struct sockaddr_in *addr; struct sockaddr_in *addr;
#ifdef ENABLE_IPV6 #ifdef ENABLE_IPV6
struct sockaddr_in6 *addr6; struct sockaddr_in6 *addr6;

View file

@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#include "curl_setup.h" #include "curl_setup.h"
@ -40,7 +42,6 @@
# include <stdlib.h> # include <stdlib.h>
#endif #endif
/* /*
* Curl_addrinfo is our internal struct definition that we use to allow * Curl_addrinfo is our internal struct definition that we use to allow
* consistent internal handling of this data. We use this even when the * consistent internal handling of this data. We use this even when the
@ -58,29 +59,29 @@ struct Curl_addrinfo {
struct sockaddr *ai_addr; struct sockaddr *ai_addr;
struct Curl_addrinfo *ai_next; struct Curl_addrinfo *ai_next;
}; };
typedef struct Curl_addrinfo Curl_addrinfo;
void void
Curl_freeaddrinfo(Curl_addrinfo *cahead); Curl_freeaddrinfo(struct Curl_addrinfo *cahead);
#ifdef HAVE_GETADDRINFO #ifdef HAVE_GETADDRINFO
int int
Curl_getaddrinfo_ex(const char *nodename, Curl_getaddrinfo_ex(const char *nodename,
const char *servname, const char *servname,
const struct addrinfo *hints, const struct addrinfo *hints,
Curl_addrinfo **result); struct Curl_addrinfo **result);
#endif #endif
Curl_addrinfo * struct Curl_addrinfo *
Curl_he2ai(const struct hostent *he, int port); Curl_he2ai(const struct hostent *he, int port);
Curl_addrinfo * struct Curl_addrinfo *
Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port); Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port);
Curl_addrinfo *Curl_str2addr(char *dotted, int port); struct Curl_addrinfo *Curl_str2addr(char *dotted, int port);
#ifdef USE_UNIX_SOCKETS #ifdef USE_UNIX_SOCKETS
Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract); struct Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath,
bool abstract);
#endif #endif
#if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) && \ #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) && \
@ -98,7 +99,7 @@ curl_dbg_getaddrinfo(const char *hostname, const char *service,
#ifdef HAVE_GETADDRINFO #ifdef HAVE_GETADDRINFO
#ifdef USE_RESOLVE_ON_IPS #ifdef USE_RESOLVE_ON_IPS
void Curl_addrinfo_set_port(Curl_addrinfo *addrinfo, int port); void Curl_addrinfo_set_port(struct Curl_addrinfo *addrinfo, int port);
#else #else
#define Curl_addrinfo_set_port(x,y) #define Curl_addrinfo_set_port(x,y)
#endif #endif

View file

@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -20,15 +20,14 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
CURLcode Curl_base64_encode(struct Curl_easy *data, CURLcode Curl_base64_encode(const char *inputbuff, size_t insize,
const char *inputbuff, size_t insize,
char **outptr, size_t *outlen); char **outptr, size_t *outlen);
CURLcode Curl_base64url_encode(struct Curl_easy *data, CURLcode Curl_base64url_encode(const char *inputbuff, size_t insize,
const char *inputbuff, size_t insize,
char **outptr, size_t *outlen); char **outptr, size_t *outlen);
CURLcode Curl_base64_decode(const char *src, CURLcode Curl_base64_decode(const char *src,
unsigned char **outptr, size_t *outlen); unsigned char **outptr, size_t *outlen);

View file

@ -1,60 +1,113 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
/* lib/curl_config.h.in. Generated somehow by cmake. */ /* lib/curl_config.h.in. Generated somehow by cmake. */
/* when building libcurl itself */ /* disables alt-svc */
#cmakedefine BUILDING_LIBCURL 1 #cmakedefine CURL_DISABLE_ALTSVC 1
/* to disable cookies support */ /* disables cookies support */
#cmakedefine CURL_DISABLE_COOKIES 1 #cmakedefine CURL_DISABLE_COOKIES 1
/* to disable cryptographic authentication */ /* disables cryptographic authentication */
#cmakedefine CURL_DISABLE_CRYPTO_AUTH 1 #cmakedefine CURL_DISABLE_CRYPTO_AUTH 1
/* to disable DICT */ /* disables DICT */
#cmakedefine CURL_DISABLE_DICT 1 #cmakedefine CURL_DISABLE_DICT 1
/* to disable FILE */ /* disables DNS-over-HTTPS */
#cmakedefine CURL_DISABLE_DOH 1
/* disables FILE */
#cmakedefine CURL_DISABLE_FILE 1 #cmakedefine CURL_DISABLE_FILE 1
/* to disable FTP */ /* disables FTP */
#cmakedefine CURL_DISABLE_FTP 1 #cmakedefine CURL_DISABLE_FTP 1
/* to disable GOPHER */ /* disables GOPHER */
#cmakedefine CURL_DISABLE_GOPHER 1 #cmakedefine CURL_DISABLE_GOPHER 1
/* to disable IMAP */ /* disables HSTS support */
#cmakedefine CURL_DISABLE_IMAP 1 #cmakedefine CURL_DISABLE_HSTS 1
/* to disable HTTP */ /* disables HTTP */
#cmakedefine CURL_DISABLE_HTTP 1 #cmakedefine CURL_DISABLE_HTTP 1
/* to disable LDAP */ /* disables IMAP */
#cmakedefine CURL_DISABLE_IMAP 1
/* disables LDAP */
#cmakedefine CURL_DISABLE_LDAP 1 #cmakedefine CURL_DISABLE_LDAP 1
/* to disable LDAPS */ /* disables LDAPS */
#cmakedefine CURL_DISABLE_LDAPS 1 #cmakedefine CURL_DISABLE_LDAPS 1
/* to disable POP3 */ /* disables --libcurl option from the curl tool */
#cmakedefine CURL_DISABLE_LIBCURL_OPTION 1
/* disables MIME support */
#cmakedefine CURL_DISABLE_MIME 1
/* disables MQTT */
#cmakedefine CURL_DISABLE_MQTT 1
/* disables netrc parser */
#cmakedefine CURL_DISABLE_NETRC 1
/* disables NTLM support */
#cmakedefine CURL_DISABLE_NTLM 1
/* disables date parsing */
#cmakedefine CURL_DISABLE_PARSEDATE 1
/* disables POP3 */
#cmakedefine CURL_DISABLE_POP3 1 #cmakedefine CURL_DISABLE_POP3 1
/* to disable proxies */ /* disables built-in progress meter */
#cmakedefine CURL_DISABLE_PROGRESS_METER 1
/* disables proxies */
#cmakedefine CURL_DISABLE_PROXY 1 #cmakedefine CURL_DISABLE_PROXY 1
/* to disable RTSP */ /* disables RTSP */
#cmakedefine CURL_DISABLE_RTSP 1 #cmakedefine CURL_DISABLE_RTSP 1
/* to disable SMB */ /* disables SMB */
#cmakedefine CURL_DISABLE_SMB 1 #cmakedefine CURL_DISABLE_SMB 1
/* to disable SMTP */ /* disables SMTP */
#cmakedefine CURL_DISABLE_SMTP 1 #cmakedefine CURL_DISABLE_SMTP 1
/* to disable TELNET */ /* disables use of socketpair for curl_multi_poll */
#cmakedefine CURL_DISABLE_SOCKETPAIR 1
/* disables TELNET */
#cmakedefine CURL_DISABLE_TELNET 1 #cmakedefine CURL_DISABLE_TELNET 1
/* to disable TFTP */ /* disables TFTP */
#cmakedefine CURL_DISABLE_TFTP 1 #cmakedefine CURL_DISABLE_TFTP 1
/* to disable verbose strings */ /* disables verbose strings */
#cmakedefine CURL_DISABLE_VERBOSE_STRINGS 1 #cmakedefine CURL_DISABLE_VERBOSE_STRINGS 1
/* to make a symbol visible */ /* to make a symbol visible */
@ -64,6 +117,9 @@
#define CURL_EXTERN_SYMBOL #define CURL_EXTERN_SYMBOL
#endif #endif
/* Allow SMB to work on Windows */
#cmakedefine USE_WIN32_CRYPTO 1
/* Use Windows LDAP implementation */ /* Use Windows LDAP implementation */
#cmakedefine USE_WIN32_LDAP 1 #cmakedefine USE_WIN32_LDAP 1
@ -76,41 +132,20 @@
/* Define if you want to enable IPv6 support */ /* Define if you want to enable IPv6 support */
#cmakedefine ENABLE_IPV6 1 #cmakedefine ENABLE_IPV6 1
/* Define to the type qualifier of arg 1 for getnameinfo. */
#cmakedefine GETNAMEINFO_QUAL_ARG1 ${GETNAMEINFO_QUAL_ARG1}
/* Define to the type of arg 1 for getnameinfo. */
#cmakedefine GETNAMEINFO_TYPE_ARG1 ${GETNAMEINFO_TYPE_ARG1}
/* Define to the type of arg 2 for getnameinfo. */
#cmakedefine GETNAMEINFO_TYPE_ARG2 ${GETNAMEINFO_TYPE_ARG2}
/* Define to the type of args 4 and 6 for getnameinfo. */
#cmakedefine GETNAMEINFO_TYPE_ARG46 ${GETNAMEINFO_TYPE_ARG46}
/* Define to the type of arg 7 for getnameinfo. */
#cmakedefine GETNAMEINFO_TYPE_ARG7 ${GETNAMEINFO_TYPE_ARG7}
/* Specifies the number of arguments to getservbyport_r */
#cmakedefine GETSERVBYPORT_R_ARGS ${GETSERVBYPORT_R_ARGS}
/* Specifies the size of the buffer to pass to getservbyport_r */
#cmakedefine GETSERVBYPORT_R_BUFSIZE ${GETSERVBYPORT_R_BUFSIZE}
/* Define to 1 if you have the alarm function. */ /* Define to 1 if you have the alarm function. */
#cmakedefine HAVE_ALARM 1 #cmakedefine HAVE_ALARM 1
/* Define to 1 if you have the <alloca.h> header file. */
#cmakedefine HAVE_ALLOCA_H 1
/* Define to 1 if you have the <arpa/inet.h> header file. */ /* Define to 1 if you have the <arpa/inet.h> header file. */
#cmakedefine HAVE_ARPA_INET_H 1 #cmakedefine HAVE_ARPA_INET_H 1
/* Define to 1 if you have the <arpa/tftp.h> header file. */ /* Define to 1 if you have the <arpa/tftp.h> header file. */
#cmakedefine HAVE_ARPA_TFTP_H 1 #cmakedefine HAVE_ARPA_TFTP_H 1
/* Define to 1 if you have the <assert.h> header file. */ /* Define to 1 if you have _Atomic support. */
#cmakedefine HAVE_ASSERT_H 1 #cmakedefine HAVE_ATOMIC 1
/* Define to 1 if you have the `fchmod' function. */
#cmakedefine HAVE_FCHMOD 1
/* Define to 1 if you have the `basename' function. */ /* Define to 1 if you have the `basename' function. */
#cmakedefine HAVE_BASENAME 1 #cmakedefine HAVE_BASENAME 1
@ -127,27 +162,6 @@
/* Define to 1 if you have the `closesocket' function. */ /* Define to 1 if you have the `closesocket' function. */
#cmakedefine HAVE_CLOSESOCKET 1 #cmakedefine HAVE_CLOSESOCKET 1
/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */
#cmakedefine HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1
/* Define to 1 if you have the <crypto.h> header file. */
#cmakedefine HAVE_CRYPTO_H 1
/* Define to 1 if you have the <des.h> header file. */
#cmakedefine HAVE_DES_H 1
/* 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
/* Define to 1 if you have the <err.h> header file. */
#cmakedefine HAVE_ERR_H 1
/* Define to 1 if you have the fcntl function. */ /* Define to 1 if you have the fcntl function. */
#cmakedefine HAVE_FCNTL 1 #cmakedefine HAVE_FCNTL 1
@ -157,44 +171,23 @@
/* Define to 1 if you have a working fcntl O_NONBLOCK function. */ /* Define to 1 if you have a working fcntl O_NONBLOCK function. */
#cmakedefine HAVE_FCNTL_O_NONBLOCK 1 #cmakedefine HAVE_FCNTL_O_NONBLOCK 1
/* Define to 1 if you have the fdopen function. */
#cmakedefine HAVE_FDOPEN 1
/* Define to 1 if you have the `fork' function. */
#cmakedefine HAVE_FORK 1
/* Define to 1 if you have the freeaddrinfo function. */ /* Define to 1 if you have the freeaddrinfo function. */
#cmakedefine HAVE_FREEADDRINFO 1 #cmakedefine HAVE_FREEADDRINFO 1
/* Define to 1 if you have the freeifaddrs function. */
#cmakedefine HAVE_FREEIFADDRS 1
/* Define to 1 if you have the ftruncate function. */ /* Define to 1 if you have the ftruncate function. */
#cmakedefine HAVE_FTRUNCATE 1 #cmakedefine HAVE_FTRUNCATE 1
/* Define to 1 if you have a working getaddrinfo function. */ /* Define to 1 if you have a working getaddrinfo function. */
#cmakedefine HAVE_GETADDRINFO 1 #cmakedefine HAVE_GETADDRINFO 1
/* Define to 1 if the getaddrinfo function is threadsafe. */
#cmakedefine HAVE_GETADDRINFO_THREADSAFE 1
/* Define to 1 if you have the `geteuid' function. */ /* Define to 1 if you have the `geteuid' function. */
#cmakedefine HAVE_GETEUID 1 #cmakedefine HAVE_GETEUID 1
/* Define to 1 if you have the gethostbyaddr function. */ /* Define to 1 if you have the `getppid' function. */
#cmakedefine HAVE_GETHOSTBYADDR 1 #cmakedefine HAVE_GETPPID 1
/* Define to 1 if you have the gethostbyaddr_r function. */
#cmakedefine HAVE_GETHOSTBYADDR_R 1
/* gethostbyaddr_r() takes 5 args */
#cmakedefine HAVE_GETHOSTBYADDR_R_5 1
/* gethostbyaddr_r() takes 7 args */
#cmakedefine HAVE_GETHOSTBYADDR_R_7 1
/* gethostbyaddr_r() takes 8 args */
#cmakedefine HAVE_GETHOSTBYADDR_R_8 1
/* Define to 1 if you have the gethostbyname function. */
#cmakedefine HAVE_GETHOSTBYNAME 1
/* Define to 1 if you have the gethostbyname_r function. */ /* Define to 1 if you have the gethostbyname_r function. */
#cmakedefine HAVE_GETHOSTBYNAME_R 1 #cmakedefine HAVE_GETHOSTBYNAME_R 1
@ -214,24 +207,21 @@
/* Define to 1 if you have a working getifaddrs function. */ /* Define to 1 if you have a working getifaddrs function. */
#cmakedefine HAVE_GETIFADDRS 1 #cmakedefine HAVE_GETIFADDRS 1
/* Define to 1 if you have the getnameinfo function. */
#cmakedefine HAVE_GETNAMEINFO 1
/* Define to 1 if you have the `getpass_r' function. */ /* Define to 1 if you have the `getpass_r' function. */
#cmakedefine HAVE_GETPASS_R 1 #cmakedefine HAVE_GETPASS_R 1
/* Define to 1 if you have the `getppid' function. */ /* Define to 1 if you have the `getppid' function. */
#cmakedefine HAVE_GETPPID 1 #cmakedefine HAVE_GETPPID 1
/* Define to 1 if you have the `getprotobyname' function. */
#cmakedefine HAVE_GETPROTOBYNAME 1
/* Define to 1 if you have the `getpeername' function. */ /* Define to 1 if you have the `getpeername' function. */
#cmakedefine HAVE_GETPEERNAME 1 #cmakedefine HAVE_GETPEERNAME 1
/* Define to 1 if you have the `getsockname' function. */ /* Define to 1 if you have the `getsockname' function. */
#cmakedefine HAVE_GETSOCKNAME 1 #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. */ /* Define to 1 if you have the `getpwuid' function. */
#cmakedefine HAVE_GETPWUID 1 #cmakedefine HAVE_GETPWUID 1
@ -241,9 +231,6 @@
/* Define to 1 if you have the `getrlimit' function. */ /* Define to 1 if you have the `getrlimit' function. */
#cmakedefine HAVE_GETRLIMIT 1 #cmakedefine HAVE_GETRLIMIT 1
/* Define to 1 if you have the getservbyport_r function. */
#cmakedefine HAVE_GETSERVBYPORT_R 1
/* Define to 1 if you have the `gettimeofday' function. */ /* Define to 1 if you have the `gettimeofday' function. */
#cmakedefine HAVE_GETTIMEOFDAY 1 #cmakedefine HAVE_GETTIMEOFDAY 1
@ -277,39 +264,24 @@
/* Define to 1 if you have the `idna_strerror' function. */ /* Define to 1 if you have the `idna_strerror' function. */
#cmakedefine HAVE_IDNA_STRERROR 1 #cmakedefine HAVE_IDNA_STRERROR 1
/* Define to 1 if you have the `idn_free' function. */
#cmakedefine HAVE_IDN_FREE 1
/* Define to 1 if you have the <idn-free.h> header file. */
#cmakedefine HAVE_IDN_FREE_H 1
/* Define to 1 if you have the <ifaddrs.h> header file. */ /* Define to 1 if you have the <ifaddrs.h> header file. */
#cmakedefine HAVE_IFADDRS_H 1 #cmakedefine HAVE_IFADDRS_H 1
/* Define to 1 if you have the `inet_addr' function. */
#cmakedefine HAVE_INET_ADDR 1
/* Define to 1 if you have the inet_ntoa_r function. */
#cmakedefine HAVE_INET_NTOA_R 1
/* inet_ntoa_r() takes 2 args */
#cmakedefine HAVE_INET_NTOA_R_2 1
/* inet_ntoa_r() takes 3 args */
#cmakedefine HAVE_INET_NTOA_R_3 1
/* Define to 1 if you have a IPv6 capable working inet_ntop function. */ /* Define to 1 if you have a IPv6 capable working inet_ntop function. */
#cmakedefine HAVE_INET_NTOP 1 #cmakedefine HAVE_INET_NTOP 1
/* Define to 1 if you have a IPv6 capable working inet_pton function. */ /* Define to 1 if you have a IPv6 capable working inet_pton function. */
#cmakedefine HAVE_INET_PTON 1 #cmakedefine HAVE_INET_PTON 1
/* Define to 1 if symbol `sa_family_t' exists */
#cmakedefine HAVE_SA_FAMILY_T 1
/* Define to 1 if symbol `ADDRESS_FAMILY' exists */
#cmakedefine HAVE_ADDRESS_FAMILY 1
/* Define to 1 if you have the <inttypes.h> header file. */ /* Define to 1 if you have the <inttypes.h> header file. */
#cmakedefine HAVE_INTTYPES_H 1 #cmakedefine HAVE_INTTYPES_H 1
/* Define to 1 if you have the ioctl function. */
#cmakedefine HAVE_IOCTL 1
/* Define to 1 if you have the ioctlsocket function. */ /* Define to 1 if you have the ioctlsocket function. */
#cmakedefine HAVE_IOCTLSOCKET 1 #cmakedefine HAVE_IOCTLSOCKET 1
@ -332,21 +304,9 @@
/* Define to 1 if you have the <io.h> header file. */ /* Define to 1 if you have the <io.h> header file. */
#cmakedefine HAVE_IO_H 1 #cmakedefine HAVE_IO_H 1
/* if you have the Kerberos4 libraries (including -ldes) */
#cmakedefine HAVE_KRB4 1
/* Define to 1 if you have the `krb_get_our_ip_for_realm' function. */
#cmakedefine HAVE_KRB_GET_OUR_IP_FOR_REALM 1
/* Define to 1 if you have the <krb.h> header file. */
#cmakedefine HAVE_KRB_H 1
/* Define to 1 if you have the lber.h header file. */ /* Define to 1 if you have the lber.h header file. */
#cmakedefine HAVE_LBER_H 1 #cmakedefine HAVE_LBER_H 1
/* Define to 1 if you have the ldapssl.h header file. */
#cmakedefine HAVE_LDAPSSL_H 1
/* Define to 1 if you have the ldap.h header file. */ /* Define to 1 if you have the ldap.h header file. */
#cmakedefine HAVE_LDAP_H 1 #cmakedefine HAVE_LDAP_H 1
@ -362,14 +322,11 @@
/* Define to 1 if you have the <libgen.h> header file. */ /* Define to 1 if you have the <libgen.h> header file. */
#cmakedefine HAVE_LIBGEN_H 1 #cmakedefine HAVE_LIBGEN_H 1
/* Define to 1 if you have the `idn' library (-lidn). */ /* Define to 1 if you have the `idn2' library (-lidn2). */
#cmakedefine HAVE_LIBIDN 1 #cmakedefine HAVE_LIBIDN2 1
/* Define to 1 if you have the `resolv' library (-lresolv). */ /* Define to 1 if you have the idn2.h header file. */
#cmakedefine HAVE_LIBRESOLV 1 #cmakedefine HAVE_IDN2_H 1
/* Define to 1 if you have the `resolve' library (-lresolve). */
#cmakedefine HAVE_LIBRESOLVE 1
/* Define to 1 if you have the `socket' library (-lsocket). */ /* Define to 1 if you have the `socket' library (-lsocket). */
#cmakedefine HAVE_LIBSOCKET 1 #cmakedefine HAVE_LIBSOCKET 1
@ -377,27 +334,6 @@
/* Define to 1 if you have the `ssh2' library (-lssh2). */ /* Define to 1 if you have the `ssh2' library (-lssh2). */
#cmakedefine HAVE_LIBSSH2 1 #cmakedefine HAVE_LIBSSH2 1
/* Define to 1 if libssh2 provides `libssh2_version'. */
#cmakedefine HAVE_LIBSSH2_VERSION 1
/* Define to 1 if libssh2 provides `libssh2_init'. */
#cmakedefine HAVE_LIBSSH2_INIT 1
/* Define to 1 if libssh2 provides `libssh2_exit'. */
#cmakedefine HAVE_LIBSSH2_EXIT 1
/* Define to 1 if libssh2 provides `libssh2_scp_send64'. */
#cmakedefine HAVE_LIBSSH2_SCP_SEND64 1
/* Define to 1 if libssh2 provides `libssh2_session_handshake'. */
#cmakedefine HAVE_LIBSSH2_SESSION_HANDSHAKE 1
/* 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 */ /* if zlib is available */
#cmakedefine HAVE_LIBZ 1 #cmakedefine HAVE_LIBZ 1
@ -407,21 +343,15 @@
/* if your compiler supports LL */ /* if your compiler supports LL */
#cmakedefine HAVE_LL 1 #cmakedefine HAVE_LL 1
/* if zstd is available */
#cmakedefine HAVE_ZSTD 1
/* Define to 1 if you have the <locale.h> header file. */ /* Define to 1 if you have the <locale.h> header file. */
#cmakedefine HAVE_LOCALE_H 1 #cmakedefine HAVE_LOCALE_H 1
/* Define to 1 if you have a working localtime_r function. */
#cmakedefine HAVE_LOCALTIME_R 1
/* Define to 1 if the compiler supports the 'long long' data type. */ /* Define to 1 if the compiler supports the 'long long' data type. */
#cmakedefine HAVE_LONGLONG 1 #cmakedefine HAVE_LONGLONG 1
/* Define to 1 if you have the malloc.h header file. */
#cmakedefine HAVE_MALLOC_H 1
/* Define to 1 if you have the <memory.h> header file. */
#cmakedefine HAVE_MEMORY_H 1
/* Define to 1 if you have the MSG_NOSIGNAL flag. */ /* Define to 1 if you have the MSG_NOSIGNAL flag. */
#cmakedefine HAVE_MSG_NOSIGNAL 1 #cmakedefine HAVE_MSG_NOSIGNAL 1
@ -434,51 +364,18 @@
/* Define to 1 if you have the <netinet/tcp.h> header file. */ /* Define to 1 if you have the <netinet/tcp.h> header file. */
#cmakedefine HAVE_NETINET_TCP_H 1 #cmakedefine HAVE_NETINET_TCP_H 1
/* Define to 1 if you have the <linux/tcp.h> header file. */
#cmakedefine HAVE_LINUX_TCP_H 1
/* Define to 1 if you have the <net/if.h> header file. */ /* Define to 1 if you have the <net/if.h> header file. */
#cmakedefine HAVE_NET_IF_H 1 #cmakedefine HAVE_NET_IF_H 1
/* Define to 1 if NI_WITHSCOPEID exists and works. */
#cmakedefine HAVE_NI_WITHSCOPEID 1
/* if you have an old MIT gssapi library, lacking GSS_C_NT_HOSTBASED_SERVICE */ /* if you have an old MIT gssapi library, lacking GSS_C_NT_HOSTBASED_SERVICE */
#cmakedefine HAVE_OLD_GSSMIT 1 #cmakedefine HAVE_OLD_GSSMIT 1
/* 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
/* Define to 1 if you have the <openssl/pem.h> header file. */
#cmakedefine HAVE_OPENSSL_PEM_H 1
/* Define to 1 if you have the <openssl/pkcs12.h> header file. */
#cmakedefine HAVE_OPENSSL_PKCS12_H 1
/* Define to 1 if you have the <openssl/rsa.h> header file. */
#cmakedefine HAVE_OPENSSL_RSA_H 1
/* Define to 1 if you have the <openssl/ssl.h> header file. */
#cmakedefine HAVE_OPENSSL_SSL_H 1
/* Define to 1 if you have the <openssl/x509.h> header file. */
#cmakedefine HAVE_OPENSSL_X509_H 1
/* Define to 1 if you have the <pem.h> header file. */
#cmakedefine HAVE_PEM_H 1
/* Define to 1 if you have the `perror' function. */
#cmakedefine HAVE_PERROR 1
/* Define to 1 if you have the `pipe' function. */ /* Define to 1 if you have the `pipe' function. */
#cmakedefine HAVE_PIPE 1 #cmakedefine HAVE_PIPE 1
/* Define to 1 if you have a working poll function. */
#cmakedefine HAVE_POLL 1
/* If you have a fine poll */ /* If you have a fine poll */
#cmakedefine HAVE_POLL_FINE 1 #cmakedefine HAVE_POLL_FINE 1
@ -497,21 +394,9 @@
/* Define to 1 if you have the `RAND_egd' function. */ /* Define to 1 if you have the `RAND_egd' function. */
#cmakedefine HAVE_RAND_EGD 1 #cmakedefine HAVE_RAND_EGD 1
/* Define to 1 if you have the `RAND_screen' function. */
#cmakedefine HAVE_RAND_SCREEN 1
/* Define to 1 if you have the `RAND_status' function. */
#cmakedefine HAVE_RAND_STATUS 1
/* Define to 1 if you have the recv function. */ /* Define to 1 if you have the recv function. */
#cmakedefine HAVE_RECV 1 #cmakedefine HAVE_RECV 1
/* Define to 1 if you have the recvfrom function. */
#cmakedefine HAVE_RECVFROM 1
/* Define to 1 if you have the <rsa.h> header file. */
#cmakedefine HAVE_RSA_H 1
/* Define to 1 if you have the select function. */ /* Define to 1 if you have the select function. */
#cmakedefine HAVE_SELECT 1 #cmakedefine HAVE_SELECT 1
@ -539,15 +424,9 @@
/* Define to 1 if you have the `setrlimit' function. */ /* Define to 1 if you have the `setrlimit' function. */
#cmakedefine HAVE_SETRLIMIT 1 #cmakedefine HAVE_SETRLIMIT 1
/* Define to 1 if you have the setsockopt function. */
#cmakedefine HAVE_SETSOCKOPT 1
/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */ /* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */
#cmakedefine HAVE_SETSOCKOPT_SO_NONBLOCK 1 #cmakedefine HAVE_SETSOCKOPT_SO_NONBLOCK 1
/* Define to 1 if you have the <sgtty.h> header file. */
#cmakedefine HAVE_SGTTY_H 1
/* Define to 1 if you have the sigaction function. */ /* Define to 1 if you have the sigaction function. */
#cmakedefine HAVE_SIGACTION 1 #cmakedefine HAVE_SIGACTION 1
@ -563,42 +442,33 @@
/* Define to 1 if you have the sigsetjmp function or macro. */ /* Define to 1 if you have the sigsetjmp function or macro. */
#cmakedefine HAVE_SIGSETJMP 1 #cmakedefine HAVE_SIGSETJMP 1
/* Define to 1 if sig_atomic_t is an available typedef. */
#cmakedefine HAVE_SIG_ATOMIC_T 1
/* Define to 1 if sig_atomic_t is already defined as volatile. */
#cmakedefine HAVE_SIG_ATOMIC_T_VOLATILE 1
/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */ /* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */
#cmakedefine HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1 #cmakedefine HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
/* Define to 1 if you have the `socket' function. */ /* Define to 1 if you have the `socket' function. */
#cmakedefine HAVE_SOCKET 1 #cmakedefine HAVE_SOCKET 1
/* Define to 1 if you have the `SSL_get_shutdown' function. */ /* Define to 1 if you have the socketpair function. */
#cmakedefine HAVE_SSL_GET_SHUTDOWN 1 #cmakedefine HAVE_SOCKETPAIR 1
/* Define to 1 if you have the <ssl.h> header file. */ /* Define to 1 if you have the <ssl.h> header file. */
#cmakedefine HAVE_SSL_H 1 #cmakedefine HAVE_SSL_H 1
/* Define to 1 if you have the <stdatomic.h> header file. */
#cmakedefine HAVE_STDATOMIC_H 1
/* Define to 1 if you have the <stdbool.h> header file. */ /* Define to 1 if you have the <stdbool.h> header file. */
#cmakedefine HAVE_STDBOOL_H 1 #cmakedefine HAVE_STDBOOL_H 1
/* Define to 1 if you have the <stdint.h> header file. */ /* Define to 1 if you have the <stdint.h> header file. */
#cmakedefine HAVE_STDINT_H 1 #cmakedefine HAVE_STDINT_H 1
/* Define to 1 if you have the <stdio.h> header file. */
#cmakedefine HAVE_STDIO_H 1
/* Define to 1 if you have the <stdlib.h> header file. */ /* Define to 1 if you have the <stdlib.h> header file. */
#cmakedefine HAVE_STDLIB_H 1 #cmakedefine HAVE_STDLIB_H 1
/* Define to 1 if you have the strcasecmp function. */ /* Define to 1 if you have the strcasecmp function. */
#cmakedefine HAVE_STRCASECMP 1 #cmakedefine HAVE_STRCASECMP 1
/* Define to 1 if you have the strcasestr function. */
#cmakedefine HAVE_STRCASESTR 1
/* Define to 1 if you have the strcmpi function. */ /* Define to 1 if you have the strcmpi function. */
#cmakedefine HAVE_STRCMPI 1 #cmakedefine HAVE_STRCMPI 1
@ -617,27 +487,9 @@
/* Define to 1 if you have the <string.h> header file. */ /* Define to 1 if you have the <string.h> header file. */
#cmakedefine HAVE_STRING_H 1 #cmakedefine HAVE_STRING_H 1
/* Define to 1 if you have the strlcat function. */
#cmakedefine HAVE_STRLCAT 1
/* Define to 1 if you have the `strlcpy' function. */
#cmakedefine HAVE_STRLCPY 1
/* Define to 1 if you have the strncasecmp function. */
#cmakedefine HAVE_STRNCASECMP 1
/* Define to 1 if you have the strncmpi function. */
#cmakedefine HAVE_STRNCMPI 1
/* Define to 1 if you have the strnicmp function. */
#cmakedefine HAVE_STRNICMP 1
/* Define to 1 if you have the <stropts.h> header file. */ /* Define to 1 if you have the <stropts.h> header file. */
#cmakedefine HAVE_STROPTS_H 1 #cmakedefine HAVE_STROPTS_H 1
/* Define to 1 if you have the strstr function. */
#cmakedefine HAVE_STRSTR 1
/* Define to 1 if you have the strtok_r function. */ /* Define to 1 if you have the strtok_r function. */
#cmakedefine HAVE_STRTOK_R 1 #cmakedefine HAVE_STRTOK_R 1
@ -683,9 +535,6 @@
/* Define to 1 if you have the <sys/types.h> header file. */ /* Define to 1 if you have the <sys/types.h> header file. */
#cmakedefine HAVE_SYS_TYPES_H 1 #cmakedefine HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <sys/uio.h> header file. */
#cmakedefine HAVE_SYS_UIO_H 1
/* Define to 1 if you have the <sys/un.h> header file. */ /* Define to 1 if you have the <sys/un.h> header file. */
#cmakedefine HAVE_SYS_UN_H 1 #cmakedefine HAVE_SYS_UN_H 1
@ -701,21 +550,15 @@
/* Define to 1 if you have the <time.h> header file. */ /* Define to 1 if you have the <time.h> header file. */
#cmakedefine HAVE_TIME_H 1 #cmakedefine HAVE_TIME_H 1
/* Define to 1 if you have the <tld.h> header file. */
#cmakedefine HAVE_TLD_H 1
/* Define to 1 if you have the `tld_strerror' function. */
#cmakedefine HAVE_TLD_STRERROR 1
/* Define to 1 if you have the `uname' function. */
#cmakedefine HAVE_UNAME 1
/* Define to 1 if you have the <unistd.h> header file. */ /* Define to 1 if you have the <unistd.h> header file. */
#cmakedefine HAVE_UNISTD_H 1 #cmakedefine HAVE_UNISTD_H 1
/* Define to 1 if you have the `utime' function. */ /* Define to 1 if you have the `utime' function. */
#cmakedefine HAVE_UTIME 1 #cmakedefine HAVE_UTIME 1
/* Define to 1 if you have the `utimes' function. */
#cmakedefine HAVE_UTIMES 1
/* Define to 1 if you have the <utime.h> header file. */ /* Define to 1 if you have the <utime.h> header file. */
#cmakedefine HAVE_UTIME_H 1 #cmakedefine HAVE_UTIME_H 1
@ -725,9 +568,6 @@
/* Define to 1 if compiler supports old gcc variadic macro style. */ /* Define to 1 if compiler supports old gcc variadic macro style. */
#cmakedefine HAVE_VARIADIC_MACROS_GCC 1 #cmakedefine HAVE_VARIADIC_MACROS_GCC 1
/* Define to 1 if you have the winber.h header file. */
#cmakedefine HAVE_WINBER_H 1
/* Define to 1 if you have the windows.h header file. */ /* Define to 1 if you have the windows.h header file. */
#cmakedefine HAVE_WINDOWS_H 1 #cmakedefine HAVE_WINDOWS_H 1
@ -737,34 +577,12 @@
/* Define to 1 if you have the winsock2.h header file. */ /* Define to 1 if you have the winsock2.h header file. */
#cmakedefine HAVE_WINSOCK2_H 1 #cmakedefine HAVE_WINSOCK2_H 1
/* Define to 1 if you have the winsock.h header file. */
#cmakedefine HAVE_WINSOCK_H 1
/* Define this symbol if your OS supports changing the contents of argv */ /* Define this symbol if your OS supports changing the contents of argv */
#cmakedefine HAVE_WRITABLE_ARGV 1 #cmakedefine HAVE_WRITABLE_ARGV 1
/* Define to 1 if you have the writev function. */
#cmakedefine HAVE_WRITEV 1
/* Define to 1 if you have the ws2tcpip.h header file. */ /* Define to 1 if you have the ws2tcpip.h header file. */
#cmakedefine HAVE_WS2TCPIP_H 1 #cmakedefine HAVE_WS2TCPIP_H 1
/* Define to 1 if you have the <x509.h> header file. */
#cmakedefine HAVE_X509_H 1
/* Define if you have the <process.h> header file. */
#cmakedefine HAVE_PROCESS_H 1
/* if you have the zlib.h header file */
#cmakedefine HAVE_ZLIB_H 1
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#cmakedefine LT_OBJDIR ${LT_OBJDIR}
/* If you lack a fine basename() prototype */
#cmakedefine NEED_BASENAME_PROTO 1
/* Define to 1 if you need the lber.h header file even with ldap.h */ /* Define to 1 if you need the lber.h header file even with ldap.h */
#cmakedefine NEED_LBER_H 1 #cmakedefine NEED_LBER_H 1
@ -798,123 +616,48 @@
/* a suitable file to read random data from */ /* a suitable file to read random data from */
#cmakedefine RANDOM_FILE "${RANDOM_FILE}" #cmakedefine RANDOM_FILE "${RANDOM_FILE}"
/* Define to the type of arg 1 for recvfrom. */ /*
#cmakedefine RECVFROM_TYPE_ARG1 ${RECVFROM_TYPE_ARG1} 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.
/* Define to the type pointed by arg 2 for recvfrom. */ Reference: https://cmake.org/cmake/help/latest/module/CheckTypeSize.html
#cmakedefine RECVFROM_TYPE_ARG2 ${RECVFROM_TYPE_ARG2} */
/* Define to 1 if the type pointed by arg 2 for recvfrom is void. */
#cmakedefine RECVFROM_TYPE_ARG2_IS_VOID 1
/* Define to the type of arg 3 for recvfrom. */
#cmakedefine RECVFROM_TYPE_ARG3 ${RECVFROM_TYPE_ARG3}
/* Define to the type of arg 4 for recvfrom. */
#cmakedefine RECVFROM_TYPE_ARG4 ${RECVFROM_TYPE_ARG4}
/* Define to the type pointed by arg 5 for recvfrom. */
#cmakedefine RECVFROM_TYPE_ARG5 ${RECVFROM_TYPE_ARG5}
/* Define to 1 if the type pointed by arg 5 for recvfrom is void. */
#cmakedefine RECVFROM_TYPE_ARG5_IS_VOID 1
/* Define to the type pointed by arg 6 for recvfrom. */
#cmakedefine RECVFROM_TYPE_ARG6 ${RECVFROM_TYPE_ARG6}
/* Define to 1 if the type pointed by arg 6 for recvfrom is void. */
#cmakedefine RECVFROM_TYPE_ARG6_IS_VOID 1
/* Define to the function return type for recvfrom. */
#cmakedefine RECVFROM_TYPE_RETV ${RECVFROM_TYPE_RETV}
/* Define to the type of arg 1 for recv. */
#cmakedefine RECV_TYPE_ARG1 ${RECV_TYPE_ARG1}
/* Define to the type of arg 2 for recv. */
#cmakedefine RECV_TYPE_ARG2 ${RECV_TYPE_ARG2}
/* Define to the type of arg 3 for recv. */
#cmakedefine RECV_TYPE_ARG3 ${RECV_TYPE_ARG3}
/* Define to the type of arg 4 for recv. */
#cmakedefine RECV_TYPE_ARG4 ${RECV_TYPE_ARG4}
/* Define to the function return type for recv. */
#cmakedefine RECV_TYPE_RETV ${RECV_TYPE_RETV}
/* Define as the return type of signal handlers (`int' or `void'). */
#cmakedefine RETSIGTYPE ${RETSIGTYPE}
/* Define to the type qualifier of arg 5 for select. */
#cmakedefine SELECT_QUAL_ARG5 ${SELECT_QUAL_ARG5}
/* Define to the type of arg 1 for select. */
#cmakedefine SELECT_TYPE_ARG1 ${SELECT_TYPE_ARG1}
/* Define to the type of args 2, 3 and 4 for select. */
#cmakedefine SELECT_TYPE_ARG234 ${SELECT_TYPE_ARG234}
/* Define to the type of arg 5 for select. */
#cmakedefine SELECT_TYPE_ARG5 ${SELECT_TYPE_ARG5}
/* Define to the function return type for select. */
#cmakedefine SELECT_TYPE_RETV ${SELECT_TYPE_RETV}
/* Define to the type qualifier of arg 2 for send. */
#cmakedefine SEND_QUAL_ARG2 ${SEND_QUAL_ARG2}
/* Define to the type of arg 1 for send. */
#cmakedefine SEND_TYPE_ARG1 ${SEND_TYPE_ARG1}
/* Define to the type of arg 2 for send. */
#cmakedefine SEND_TYPE_ARG2 ${SEND_TYPE_ARG2}
/* Define to the type of arg 3 for send. */
#cmakedefine SEND_TYPE_ARG3 ${SEND_TYPE_ARG3}
/* Define to the type of arg 4 for send. */
#cmakedefine SEND_TYPE_ARG4 ${SEND_TYPE_ARG4}
/* Define to the function return type for send. */
#cmakedefine SEND_TYPE_RETV ${SEND_TYPE_RETV}
/* The size of `int', as computed by sizeof. */ /* The size of `int', as computed by sizeof. */
@SIZEOF_INT_CODE@ ${SIZEOF_INT_CODE}
/* The size of `short', as computed by sizeof. */ /* The size of `short', as computed by sizeof. */
@SIZEOF_SHORT_CODE@ ${SIZEOF_SHORT_CODE}
/* The size of `long', as computed by sizeof. */ /* The size of `long', as computed by sizeof. */
@SIZEOF_LONG_CODE@ ${SIZEOF_LONG_CODE}
/* The size of `long long', as computed by sizeof. */ /* 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. */ /* The size of `__int64', as computed by sizeof. */
@SIZEOF___INT64_CODE@ ${SIZEOF___INT64_CODE}
/* The size of `off_t', as computed by sizeof. */ /* 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. */ /* 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. */ /* 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. */ /* 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. */ /* 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. */ /* Define to 1 if you have the ANSI C header files. */
#cmakedefine STDC_HEADERS 1 #cmakedefine STDC_HEADERS 1
/* Define to the type of arg 3 for strerror_r. */
#cmakedefine STRERROR_R_TYPE_ARG3 ${STRERROR_R_TYPE_ARG3}
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */ /* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
#cmakedefine TIME_WITH_SYS_TIME 1 #cmakedefine TIME_WITH_SYS_TIME 1
@ -927,39 +670,67 @@
/* Define if you want to enable WIN32 threaded DNS lookup */ /* Define if you want to enable WIN32 threaded DNS lookup */
#cmakedefine USE_THREADS_WIN32 1 #cmakedefine USE_THREADS_WIN32 1
/* Define to disable non-blocking sockets. */
#cmakedefine USE_BLOCKING_SOCKETS 1
/* if GnuTLS is enabled */ /* if GnuTLS is enabled */
#cmakedefine USE_GNUTLS 1 #cmakedefine USE_GNUTLS 1
/* if PolarSSL is enabled */
#cmakedefine USE_POLARSSL 1
/* if Secure Transport is enabled */ /* if Secure Transport is enabled */
#cmakedefine USE_SECTRANSP 1 #cmakedefine USE_SECTRANSP 1
/* if mbedTLS is enabled */ /* if mbedTLS is enabled */
#cmakedefine USE_MBEDTLS 1 #cmakedefine USE_MBEDTLS 1
/* if BearSSL is enabled */
#cmakedefine USE_BEARSSL 1
/* if WolfSSL is enabled */
#cmakedefine USE_WOLFSSL 1
/* if libSSH is in use */
#cmakedefine USE_LIBSSH 1
/* if libSSH2 is in use */ /* if libSSH2 is in use */
#cmakedefine USE_LIBSSH2 1 #cmakedefine USE_LIBSSH2 1
/* if libPSL is in use */
#cmakedefine USE_LIBPSL 1
/* If you want to build curl with the built-in manual */ /* If you want to build curl with the built-in manual */
#cmakedefine USE_MANUAL 1 #cmakedefine USE_MANUAL 1
/* if NSS is enabled */ /* if NSS is enabled */
#cmakedefine USE_NSS 1 #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 */ /* if you want to use OpenLDAP code instead of legacy ldap implementation */
#cmakedefine USE_OPENLDAP 1 #cmakedefine USE_OPENLDAP 1
/* if OpenSSL is in use */ /* if OpenSSL is in use */
#cmakedefine USE_OPENSSL 1 #cmakedefine USE_OPENSSL 1
/* Define to 1 if you don't want the OpenSSL configuration to be loaded
automatically */
#cmakedefine CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG 1
/* to enable NGHTTP2 */ /* to enable NGHTTP2 */
#cmakedefine USE_NGHTTP2 1 #cmakedefine USE_NGHTTP2 1
/* to enable NGTCP2 */
#cmakedefine USE_NGTCP2 1
/* to enable NGHTTP3 */
#cmakedefine USE_NGHTTP3 1
/* to enable quiche */
#cmakedefine USE_QUICHE 1
/* Define to 1 if you have the quiche_conn_set_qlog_fd function. */
#cmakedefine HAVE_QUICHE_CONN_SET_QLOG_FD 1
/* to enable msh3 */
#cmakedefine USE_MSH3 1
/* if Unix domain sockets are enabled */ /* if Unix domain sockets are enabled */
#cmakedefine USE_UNIX_SOCKETS #cmakedefine USE_UNIX_SOCKETS
@ -972,9 +743,6 @@
/* enable multiple SSL backends */ /* enable multiple SSL backends */
#cmakedefine CURL_WITH_MULTI_SSL 1 #cmakedefine CURL_WITH_MULTI_SSL 1
/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */
#cmakedefine USE_YASSLEMUL 1
/* Version number of package */ /* Version number of package */
#cmakedefine VERSION ${VERSION} #cmakedefine VERSION ${VERSION}
@ -1022,3 +790,9 @@
/* Define to 1 if you have the mach_absolute_time function. */ /* Define to 1 if you have the mach_absolute_time function. */
#cmakedefine HAVE_MACH_ABSOLUTE_TIME 1 #cmakedefine HAVE_MACH_ABSOLUTE_TIME 1
/* to enable Windows IDN */
#cmakedefine USE_WIN32_IDN 1
/* Define to 1 to enable websocket support. */
#cmakedefine USE_WEBSOCKETS 1

View file

@ -1,133 +0,0 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#include "curl_setup.h"
#ifndef CURL_DOES_CONVERSIONS
#undef _U
#define _U (1<<0) /* upper case */
#undef _L
#define _L (1<<1) /* lower case */
#undef _N
#define _N (1<<2) /* decimal numerical digit */
#undef _S
#define _S (1<<3) /* space */
#undef _P
#define _P (1<<4) /* punctuation */
#undef _C
#define _C (1<<5) /* control */
#undef _X
#define _X (1<<6) /* hexadecimal letter */
#undef _B
#define _B (1<<7) /* blank */
static const unsigned char ascii[128] = {
_C, _C, _C, _C, _C, _C, _C, _C,
_C, _C|_S, _C|_S, _C|_S, _C|_S, _C|_S, _C, _C,
_C, _C, _C, _C, _C, _C, _C, _C,
_C, _C, _C, _C, _C, _C, _C, _C,
_S|_B, _P, _P, _P, _P, _P, _P, _P,
_P, _P, _P, _P, _P, _P, _P, _P,
_N, _N, _N, _N, _N, _N, _N, _N,
_N, _N, _P, _P, _P, _P, _P, _P,
_P, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U,
_U, _U, _U, _U, _U, _U, _U, _U,
_U, _U, _U, _U, _U, _U, _U, _U,
_U, _U, _U, _P, _P, _P, _P, _P,
_P, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L,
_L, _L, _L, _L, _L, _L, _L, _L,
_L, _L, _L, _L, _L, _L, _L, _L,
_L, _L, _L, _P, _P, _P, _P, _C
};
int Curl_isspace(int c)
{
if((c < 0) || (c >= 0x80))
return FALSE;
return (ascii[c] & _S);
}
int Curl_isdigit(int c)
{
if((c < 0) || (c >= 0x80))
return FALSE;
return (ascii[c] & _N);
}
int Curl_isalnum(int c)
{
if((c < 0) || (c >= 0x80))
return FALSE;
return (ascii[c] & (_N|_U|_L));
}
int Curl_isxdigit(int c)
{
if((c < 0) || (c >= 0x80))
return FALSE;
return (ascii[c] & (_N|_X));
}
int Curl_isgraph(int c)
{
if((c < 0) || (c >= 0x80) || (c == ' '))
return FALSE;
return (ascii[c] & (_N|_X|_U|_L|_P|_S));
}
int Curl_isprint(int c)
{
if((c < 0) || (c >= 0x80))
return FALSE;
return (ascii[c] & (_N|_X|_U|_L|_P|_S));
}
int Curl_isalpha(int c)
{
if((c < 0) || (c >= 0x80))
return FALSE;
return (ascii[c] & (_U|_L));
}
int Curl_isupper(int c)
{
if((c < 0) || (c >= 0x80))
return FALSE;
return (ascii[c] & (_U));
}
int Curl_islower(int c)
{
if((c < 0) || (c >= 0x80))
return FALSE;
return (ascii[c] & (_L));
}
int Curl_iscntrl(int c)
{
if((c < 0) || (c >= 0x80))
return FALSE;
return (ascii[c] & (_C));
}
#endif /* !CURL_DOES_CONVERSIONS */

View file

@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -20,62 +20,28 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#include "curl_setup.h" #define ISLOWHEXALHA(x) (((x) >= 'a') && ((x) <= 'f'))
#define ISUPHEXALHA(x) (((x) >= 'A') && ((x) <= 'F'))
#ifdef CURL_DOES_CONVERSIONS #define ISLOWCNTRL(x) ((unsigned char)(x) <= 0x1f)
#define IS7F(x) ((x) == 0x7f)
/* #define ISLOWPRINT(x) (((x) >= 9) && ((x) <= 0x0d))
* Uppercase macro versions of ANSI/ISO is*() functions/macros which
* avoid negative number inputs with argument byte codes > 127.
*
* For non-ASCII platforms the C library character classification routines
* are used despite being locale-dependent, because this is better than
* not to work at all.
*/
#include <ctype.h>
#define ISSPACE(x) (isspace((int) ((unsigned char)x))) #define ISPRINT(x) (ISLOWPRINT(x) || (((x) >= ' ') && ((x) <= 0x7e)))
#define ISDIGIT(x) (isdigit((int) ((unsigned char)x))) #define ISGRAPH(x) (ISLOWPRINT(x) || (((x) > ' ') && ((x) <= 0x7e)))
#define ISALNUM(x) (isalnum((int) ((unsigned char)x))) #define ISCNTRL(x) (ISLOWCNTRL(x) || IS7F(x))
#define ISXDIGIT(x) (isxdigit((int) ((unsigned char)x))) #define ISALPHA(x) (ISLOWER(x) || ISUPPER(x))
#define ISGRAPH(x) (isgraph((int) ((unsigned char)x))) #define ISXDIGIT(x) (ISDIGIT(x) || ISLOWHEXALHA(x) || ISUPHEXALHA(x))
#define ISALPHA(x) (isalpha((int) ((unsigned char)x))) #define ISALNUM(x) (ISDIGIT(x) || ISLOWER(x) || ISUPPER(x))
#define ISPRINT(x) (isprint((int) ((unsigned char)x))) #define ISUPPER(x) (((x) >= 'A') && ((x) <= 'Z'))
#define ISUPPER(x) (isupper((int) ((unsigned char)x))) #define ISLOWER(x) (((x) >= 'a') && ((x) <= 'z'))
#define ISLOWER(x) (islower((int) ((unsigned char)x))) #define ISDIGIT(x) (((x) >= '0') && ((x) <= '9'))
#define ISCNTRL(x) (iscntrl((int) ((unsigned char)x))) #define ISBLANK(x) (((x) == ' ') || ((x) == '\t'))
#define ISASCII(x) (isascii((int) ((unsigned char)x))) #define ISSPACE(x) (ISBLANK(x) || (((x) >= 0xa) && ((x) <= 0x0d)))
#else
int Curl_isspace(int c);
int Curl_isdigit(int c);
int Curl_isalnum(int c);
int Curl_isxdigit(int c);
int Curl_isgraph(int c);
int Curl_isprint(int c);
int Curl_isalpha(int c);
int Curl_isupper(int c);
int Curl_islower(int c);
int Curl_iscntrl(int c);
#define ISSPACE(x) (Curl_isspace((int) ((unsigned char)x)))
#define ISDIGIT(x) (Curl_isdigit((int) ((unsigned char)x)))
#define ISALNUM(x) (Curl_isalnum((int) ((unsigned char)x)))
#define ISXDIGIT(x) (Curl_isxdigit((int) ((unsigned char)x)))
#define ISGRAPH(x) (Curl_isgraph((int) ((unsigned char)x)))
#define ISALPHA(x) (Curl_isalpha((int) ((unsigned char)x)))
#define ISPRINT(x) (Curl_isprint((int) ((unsigned char)x)))
#define ISUPPER(x) (Curl_isupper((int) ((unsigned char)x)))
#define ISLOWER(x) (Curl_islower((int) ((unsigned char)x)))
#define ISCNTRL(x) (Curl_iscntrl((int) ((unsigned char)x)))
#define ISASCII(x) (((x) >= 0) && ((x) <= 0x80))
#endif
#define ISBLANK(x) (int)((((unsigned char)x) == ' ') || \
(((unsigned char)x) == '\t'))
#endif /* HEADER_CURL_CTYPE_H */ #endif /* HEADER_CURL_CTYPE_H */

View file

@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2015, Steve Holme, <steve_holme@hotmail.com>. * Copyright (C) Steve Holme, <steve_holme@hotmail.com>.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -18,11 +18,18 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#include "curl_setup.h" #include "curl_setup.h"
#if defined(USE_NTLM) && !defined(USE_OPENSSL) #if defined(USE_CURL_NTLM_CORE) && !defined(USE_WOLFSSL) && \
(defined(USE_GNUTLS) || \
defined(USE_NSS) || \
defined(USE_SECTRANSP) || \
defined(USE_OS400CRYPTO) || \
defined(USE_WIN32_CRYPTO))
#include "curl_des.h" #include "curl_des.h"
@ -34,7 +41,7 @@
* *
* The function is a port of the Java based oddParity() function over at: * The function is a port of the Java based oddParity() function over at:
* *
* https://davenport.sourceforge.io/ntlm.html * https://davenport.sourceforge.net/ntlm.html
* *
* Parameters: * Parameters:
* *
@ -60,4 +67,4 @@ void Curl_des_set_odd_parity(unsigned char *bytes, size_t len)
} }
} }
#endif /* USE_NTLM && !USE_OPENSSL */ #endif

View file

@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2015, Steve Holme, <steve_holme@hotmail.com>. * Copyright (C) Steve Holme, <steve_holme@hotmail.com>.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -20,15 +20,22 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#include "curl_setup.h" #include "curl_setup.h"
#if defined(USE_NTLM) && !defined(USE_OPENSSL) #if defined(USE_CURL_NTLM_CORE) && !defined(USE_WOLFSSL) && \
(defined(USE_GNUTLS) || \
defined(USE_NSS) || \
defined(USE_SECTRANSP) || \
defined(USE_OS400CRYPTO) || \
defined(USE_WIN32_CRYPTO))
/* Applies odd parity to the given byte array */ /* Applies odd parity to the given byte array */
void Curl_des_set_odd_parity(unsigned char *bytes, size_t length); void Curl_des_set_odd_parity(unsigned char *bytes, size_t length);
#endif /* USE_NTLM && !USE_OPENSSL */ #endif
#endif /* HEADER_CURL_DES_H */ #endif /* HEADER_CURL_DES_H */

View file

@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#include "curl_setup.h" #include "curl_setup.h"
@ -80,45 +82,3 @@ unsigned short Curl_read16_be(const unsigned char *buf)
return (unsigned short)(((unsigned short)buf[0] << 8) | return (unsigned short)(((unsigned short)buf[0] << 8) |
((unsigned short)buf[1])); ((unsigned short)buf[1]));
} }
/*
* write32_le()
*
* This function converts a 32-bit integer from the native endian format,
* to little endian format ready for sending down the wire.
*
* Parameters:
*
* value [in] - The 32-bit integer value.
* buffer [in] - A pointer to the output buffer.
*/
static void write32_le(const int value, unsigned char *buffer)
{
buffer[0] = (char)(value & 0x000000FF);
buffer[1] = (char)((value & 0x0000FF00) >> 8);
buffer[2] = (char)((value & 0x00FF0000) >> 16);
buffer[3] = (char)((value & 0xFF000000) >> 24);
}
#if (CURL_SIZEOF_CURL_OFF_T > 4)
/*
* Curl_write64_le()
*
* This function converts a 64-bit integer from the native endian format,
* to little endian format ready for sending down the wire.
*
* Parameters:
*
* value [in] - The 64-bit integer value.
* buffer [in] - A pointer to the output buffer.
*/
#if defined(HAVE_LONGLONG)
void Curl_write64_le(const long long value, unsigned char *buffer)
#else
void Curl_write64_le(const __int64 value, unsigned char *buffer)
#endif
{
write32_le((int)value, buffer);
write32_le((int)(value >> 32), buffer + 4);
}
#endif /* CURL_SIZEOF_CURL_OFF_T > 4 */

View file

@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
/* Converts a 16-bit integer from little endian */ /* Converts a 16-bit integer from little endian */
@ -31,16 +33,4 @@ unsigned int Curl_read32_le(const unsigned char *buf);
/* Converts a 16-bit integer from big endian */ /* Converts a 16-bit integer from big endian */
unsigned short Curl_read16_be(const unsigned char *buf); 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)
void Curl_write64_le(const long long value, unsigned char *buffer);
#else
void Curl_write64_le(const __int64 value, unsigned char *buffer);
#endif
#endif
#endif /* HEADER_CURL_ENDIAN_H */ #endif /* HEADER_CURL_ENDIAN_H */

View file

@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#include "curl_setup.h" #include "curl_setup.h"
@ -74,9 +76,9 @@ static int parsekeyword(unsigned char **pattern, unsigned char *charset)
parsekey_state state = CURLFNM_PKW_INIT; parsekey_state state = CURLFNM_PKW_INIT;
#define KEYLEN 10 #define KEYLEN 10
char keyword[KEYLEN] = { 0 }; char keyword[KEYLEN] = { 0 };
int found = FALSE;
int i; int i;
unsigned char *p = *pattern; unsigned char *p = *pattern;
bool found = FALSE;
for(i = 0; !found; i++) { for(i = 0; !found; i++) {
char c = *p++; char c = *p++;
if(i >= KEYLEN) if(i >= KEYLEN)
@ -366,14 +368,13 @@ int Curl_fnmatch(void *ptr, const char *pattern, const char *string)
*/ */
int Curl_fnmatch(void *ptr, const char *pattern, const char *string) int Curl_fnmatch(void *ptr, const char *pattern, const char *string)
{ {
int rc;
(void)ptr; /* the argument is specified by the curl_fnmatch_callback (void)ptr; /* the argument is specified by the curl_fnmatch_callback
prototype, but not used by Curl_fnmatch() */ prototype, but not used by Curl_fnmatch() */
if(!pattern || !string) { if(!pattern || !string) {
return CURL_FNMATCH_FAIL; return CURL_FNMATCH_FAIL;
} }
rc = fnmatch(pattern, string, 0);
switch(rc) { switch(fnmatch(pattern, string, 0)) {
case 0: case 0:
return CURL_FNMATCH_MATCH; return CURL_FNMATCH_MATCH;
case FNM_NOMATCH: case FNM_NOMATCH:

View file

@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#define CURL_FNMATCH_MATCH 0 #define CURL_FNMATCH_MATCH 0

View file

@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -18,38 +18,69 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#include "curl_setup.h" #include "curl_setup.h"
#if !defined(CURL_DISABLE_COOKIES) || !defined(CURL_DISABLE_ALTSVC) || \
!defined(CURL_DISABLE_HSTS) || !defined(CURL_DISABLE_NETRC)
#include "curl_get_line.h" #include "curl_get_line.h"
#include "curl_memory.h" #include "curl_memory.h"
/* The last #include file should be: */ /* The last #include file should be: */
#include "memdebug.h" #include "memdebug.h"
/* /*
* get_line() makes sure to only return complete whole lines that fit in 'len' * Curl_get_line() makes sure to only return complete whole lines that fit in
* bytes and end with a newline. * 'len' bytes and end with a newline.
*/ */
char *Curl_get_line(char *buf, int len, FILE *input) char *Curl_get_line(char *buf, int len, FILE *input)
{ {
bool partial = FALSE; bool partial = FALSE;
while(1) { while(1) {
char *b = fgets(buf, len, input); char *b = fgets(buf, len, input);
if(b) { if(b) {
size_t rlen = strlen(b); size_t rlen = strlen(b);
if(rlen && (b[rlen-1] == '\n')) {
if(!rlen)
break;
if(b[rlen-1] == '\n') {
/* b is \n terminated */
if(partial) { if(partial) {
partial = FALSE; partial = FALSE;
continue; continue;
} }
return b; return b;
} }
/* read a partial, discard the next piece that ends with newline */ else if(feof(input)) {
partial = TRUE; if(partial)
/* Line is already too large to return, ignore rest */
break;
if(rlen + 1 < (size_t) len) {
/* b is EOF terminated, insert missing \n */
b[rlen] = '\n';
b[rlen + 1] = '\0';
return b;
}
else
/* Maximum buffersize reached + EOF
* This line is impossible to add a \n to so we'll ignore it
*/
break;
}
else
/* Maximum buffersize reached */
partial = TRUE;
} }
else else
break; break;
} }
return NULL; return NULL;
} }
#endif /* if not disabled */

View file

@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
/* get_line() makes sure to only return complete whole lines that fit in 'len' /* get_line() makes sure to only return complete whole lines that fit in 'len'

View file

@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#include "curl_setup.h" #include "curl_setup.h"
@ -48,7 +50,7 @@
* For libcurl static library release builds no overriding takes place. * For libcurl static library release builds no overriding takes place.
*/ */
int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen) int Curl_gethostname(char * const name, GETHOSTNAME_TYPE_ARG2 namelen)
{ {
#ifndef HAVE_GETHOSTNAME #ifndef HAVE_GETHOSTNAME

View file

@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -20,12 +20,14 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
/* Hostname buffer size */ /* Hostname buffer size */
#define HOSTNAME_MAX 1024 #define HOSTNAME_MAX 1024
/* This returns the local machine's un-qualified hostname */ /* This returns the local machine's un-qualified hostname */
int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen); int Curl_gethostname(char * const name, GETHOSTNAME_TYPE_ARG2 namelen);
#endif /* HEADER_CURL_GETHOSTNAME_H */ #endif /* HEADER_CURL_GETHOSTNAME_H */

View file

@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2011 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#include "curl_setup.h" #include "curl_setup.h"
@ -32,10 +34,18 @@
#include "curl_memory.h" #include "curl_memory.h"
#include "memdebug.h" #include "memdebug.h"
static char spnego_oid_bytes[] = "\x2b\x06\x01\x05\x05\x02"; #if defined(__GNUC__)
gss_OID_desc Curl_spnego_mech_oid = { 6, &spnego_oid_bytes }; #define CURL_ALIGN8 __attribute__ ((aligned(8)))
static char krb5_oid_bytes[] = "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"; #else
gss_OID_desc Curl_krb5_mech_oid = { 9, &krb5_oid_bytes }; #define CURL_ALIGN8
#endif
gss_OID_desc Curl_spnego_mech_oid CURL_ALIGN8 = {
6, (char *)"\x2b\x06\x01\x05\x05\x02"
};
gss_OID_desc Curl_krb5_mech_oid CURL_ALIGN8 = {
9, (char *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"
};
OM_uint32 Curl_gss_init_sec_context( OM_uint32 Curl_gss_init_sec_context(
struct Curl_easy *data, struct Curl_easy *data,
@ -58,8 +68,8 @@ OM_uint32 Curl_gss_init_sec_context(
#ifdef GSS_C_DELEG_POLICY_FLAG #ifdef GSS_C_DELEG_POLICY_FLAG
req_flags |= GSS_C_DELEG_POLICY_FLAG; req_flags |= GSS_C_DELEG_POLICY_FLAG;
#else #else
infof(data, "warning: support for CURLGSSAPI_DELEGATION_POLICY_FLAG not " infof(data, "WARNING: support for CURLGSSAPI_DELEGATION_POLICY_FLAG not "
"compiled in\n"); "compiled in");
#endif #endif
} }
@ -87,7 +97,7 @@ static size_t display_gss_error(OM_uint32 status, int type,
OM_uint32 maj_stat; OM_uint32 maj_stat;
OM_uint32 min_stat; OM_uint32 min_stat;
OM_uint32 msg_ctx = 0; OM_uint32 msg_ctx = 0;
gss_buffer_desc status_string; gss_buffer_desc status_string = GSS_C_EMPTY_BUFFER;
do { do {
maj_stat = gss_display_status(&min_stat, maj_stat = gss_display_status(&min_stat,
@ -96,13 +106,15 @@ static size_t display_gss_error(OM_uint32 status, int type,
GSS_C_NO_OID, GSS_C_NO_OID,
&msg_ctx, &msg_ctx,
&status_string); &status_string);
if(GSS_LOG_BUFFER_LEN > len + status_string.length + 3) { if(maj_stat == GSS_S_COMPLETE && status_string.length > 0) {
len += msnprintf(buf + len, GSS_LOG_BUFFER_LEN - len, if(GSS_LOG_BUFFER_LEN > len + status_string.length + 3) {
"%.*s. ", (int)status_string.length, len += msnprintf(buf + len, GSS_LOG_BUFFER_LEN - len,
(char *)status_string.value); "%.*s. ", (int)status_string.length,
(char *)status_string.value);
}
} }
gss_release_buffer(&min_stat, &status_string); gss_release_buffer(&min_stat, &status_string);
} while(!GSS_ERROR(maj_stat) && msg_ctx != 0); } while(!GSS_ERROR(maj_stat) && msg_ctx);
return len; return len;
} }
@ -130,7 +142,11 @@ void Curl_gss_log_error(struct Curl_easy *data, const char *prefix,
display_gss_error(minor, GSS_C_MECH_CODE, buf, len); display_gss_error(minor, GSS_C_MECH_CODE, buf, len);
infof(data, "%s%s\n", prefix, buf); infof(data, "%s%s", prefix, buf);
#ifdef CURL_DISABLE_VERBOSE_STRINGS
(void)data;
(void)prefix;
#endif
} }
#endif /* HAVE_GSSAPI */ #endif /* HAVE_GSSAPI */

View file

@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2011 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#include "curl_setup.h" #include "curl_setup.h"

View file

@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -20,11 +20,17 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#ifndef CURL_DISABLE_CRYPTO_AUTH #ifndef CURL_DISABLE_CRYPTO_AUTH
typedef void (* HMAC_hinit_func)(void *context); #include <curl/curl.h>
#define HMAC_MD5_LENGTH 16
typedef CURLcode (* HMAC_hinit_func)(void *context);
typedef void (* HMAC_hupdate_func)(void *context, typedef void (* HMAC_hupdate_func)(void *context,
const unsigned char *data, const unsigned char *data,
unsigned int len); unsigned int len);
@ -32,35 +38,38 @@ typedef void (* HMAC_hfinal_func)(unsigned char *result, void *context);
/* Per-hash function HMAC parameters. */ /* Per-hash function HMAC parameters. */
struct HMAC_params {
typedef struct { HMAC_hinit_func
HMAC_hinit_func hmac_hinit; /* Initialize context procedure. */ hmac_hinit; /* Initialize context procedure. */
HMAC_hupdate_func hmac_hupdate; /* Update context with data. */ HMAC_hupdate_func hmac_hupdate; /* Update context with data. */
HMAC_hfinal_func hmac_hfinal; /* Get final result procedure. */ HMAC_hfinal_func hmac_hfinal; /* Get final result procedure. */
unsigned int hmac_ctxtsize; /* Context structure size. */ unsigned int hmac_ctxtsize; /* Context structure size. */
unsigned int hmac_maxkeylen; /* Maximum key length (bytes). */ unsigned int hmac_maxkeylen; /* Maximum key length (bytes). */
unsigned int hmac_resultlen; /* Result length (bytes). */ unsigned int hmac_resultlen; /* Result length (bytes). */
} HMAC_params; };
/* HMAC computation context. */ /* HMAC computation context. */
struct HMAC_context {
typedef struct { const struct HMAC_params *hmac_hash; /* Hash function definition. */
const HMAC_params *hmac_hash; /* Hash function definition. */
void *hmac_hashctxt1; /* Hash function context 1. */ void *hmac_hashctxt1; /* Hash function context 1. */
void *hmac_hashctxt2; /* Hash function context 2. */ void *hmac_hashctxt2; /* Hash function context 2. */
} HMAC_context; };
/* Prototypes. */ /* Prototypes. */
struct HMAC_context *Curl_HMAC_init(const struct HMAC_params *hashparams,
HMAC_context * Curl_HMAC_init(const HMAC_params *hashparams, const unsigned char *key,
const unsigned char *key, unsigned int keylen);
unsigned int keylen); int Curl_HMAC_update(struct HMAC_context *context,
int Curl_HMAC_update(HMAC_context *context,
const unsigned char *data, const unsigned char *data,
unsigned int len); unsigned int len);
int Curl_HMAC_final(HMAC_context *context, unsigned char *result); int Curl_HMAC_final(struct HMAC_context *context, unsigned char *result);
CURLcode Curl_hmacit(const struct HMAC_params *hashparams,
const unsigned char *key, const size_t keylen,
const unsigned char *data, const size_t datalen,
unsigned char *output);
#endif #endif

View file

@ -1,5 +1,5 @@
#ifndef HEADER_CURL_SECURITY_H #ifndef HEADER_CURL_KRB5_H
#define HEADER_CURL_SECURITY_H #define HEADER_CURL_KRB5_H
/*************************************************************************** /***************************************************************************
* _ _ ____ _ * _ _ ____ _
* Project ___| | | | _ \| | * Project ___| | | | _ \| |
@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -20,16 +20,17 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
struct Curl_sec_client_mech { struct Curl_sec_client_mech {
const char *name; const char *name;
size_t size; size_t size;
int (*init)(void *); int (*init)(void *);
int (*auth)(void *, struct connectdata *); int (*auth)(void *, struct Curl_easy *data, struct connectdata *);
void (*end)(void *); void (*end)(void *);
int (*check_prot)(void *, int); int (*check_prot)(void *, int);
int (*overhead)(void *, int, int);
int (*encode)(void *, const void *, int, int, void **); int (*encode)(void *, const void *, int, int, void **);
int (*decode)(void *, void *, int, int, struct connectdata *); int (*decode)(void *, void *, int, int, struct connectdata *);
}; };
@ -39,13 +40,13 @@ struct Curl_sec_client_mech {
#define AUTH_ERROR 2 #define AUTH_ERROR 2
#ifdef HAVE_GSSAPI #ifdef HAVE_GSSAPI
int Curl_sec_read_msg(struct connectdata *conn, char *, int Curl_sec_read_msg(struct Curl_easy *data, struct connectdata *conn, char *,
enum protection_level); enum protection_level);
void Curl_sec_end(struct connectdata *); void Curl_sec_end(struct connectdata *);
CURLcode Curl_sec_login(struct connectdata *); CURLcode Curl_sec_login(struct Curl_easy *, struct connectdata *);
int Curl_sec_request_prot(struct connectdata *conn, const char *level); int Curl_sec_request_prot(struct connectdata *conn, const char *level);
#else
extern struct Curl_sec_client_mech Curl_krb5_client_mech; #define Curl_sec_end(x)
#endif #endif
#endif /* HEADER_CURL_SECURITY_H */ #endif /* HEADER_CURL_KRB5_H */

View file

@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#ifndef CURL_DISABLE_LDAP #ifndef CURL_DISABLE_LDAP
extern const struct Curl_handler Curl_handler_ldap; extern const struct Curl_handler Curl_handler_ldap;

View file

@ -0,0 +1,223 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#include <curl/curl.h>
#include "curl_log.h"
#include "urldata.h"
#include "easyif.h"
#include "cfilters.h"
#include "timeval.h"
#include "multiif.h"
#include "strcase.h"
#include "cf-socket.h"
#include "connect.h"
#include "http2.h"
#include "http_proxy.h"
#include "cf-https-connect.h"
#include "socks.h"
#include "strtok.h"
#include "vtls/vtls.h"
#include "vquic/vquic.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
void Curl_debug(struct Curl_easy *data, curl_infotype type,
char *ptr, size_t size)
{
if(data->set.verbose) {
static const char s_infotype[CURLINFO_END][3] = {
"* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
if(data->set.fdebug) {
bool inCallback = Curl_is_in_callback(data);
Curl_set_in_callback(data, true);
(void)(*data->set.fdebug)(data, type, ptr, size, data->set.debugdata);
Curl_set_in_callback(data, inCallback);
}
else {
switch(type) {
case CURLINFO_TEXT:
case CURLINFO_HEADER_OUT:
case CURLINFO_HEADER_IN:
fwrite(s_infotype[type], 2, 1, data->set.err);
fwrite(ptr, size, 1, data->set.err);
break;
default: /* nada */
break;
}
}
}
}
/* Curl_failf() is for messages stating why we failed.
* The message SHALL NOT include any LF or CR.
*/
void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
{
DEBUGASSERT(!strchr(fmt, '\n'));
if(data->set.verbose || data->set.errorbuffer) {
va_list ap;
int len;
char error[CURL_ERROR_SIZE + 2];
va_start(ap, fmt);
len = mvsnprintf(error, CURL_ERROR_SIZE, fmt, ap);
if(data->set.errorbuffer && !data->state.errorbuf) {
strcpy(data->set.errorbuffer, error);
data->state.errorbuf = TRUE; /* wrote error string */
}
error[len++] = '\n';
error[len] = '\0';
Curl_debug(data, CURLINFO_TEXT, error, len);
va_end(ap);
}
}
/* Curl_infof() is for info message along the way */
#define MAXINFO 2048
void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
{
DEBUGASSERT(!strchr(fmt, '\n'));
if(data && data->set.verbose) {
va_list ap;
int len;
char buffer[MAXINFO + 2];
va_start(ap, fmt);
len = mvsnprintf(buffer, MAXINFO, fmt, ap);
va_end(ap);
buffer[len++] = '\n';
buffer[len] = '\0';
Curl_debug(data, CURLINFO_TEXT, buffer, len);
}
}
#ifdef DEBUGBUILD
void Curl_log_cf_debug(struct Curl_easy *data, struct Curl_cfilter *cf,
const char *fmt, ...)
{
DEBUGASSERT(cf);
if(data && Curl_log_cf_is_debug(cf)) {
va_list ap;
int len;
char buffer[MAXINFO + 2];
len = msnprintf(buffer, MAXINFO, "[CONN-%ld%s-%s] ",
cf->conn->connection_id, cf->sockindex? "/2" : "",
cf->cft->name);
va_start(ap, fmt);
len += mvsnprintf(buffer + len, MAXINFO - len, fmt, ap);
va_end(ap);
buffer[len++] = '\n';
buffer[len] = '\0';
Curl_debug(data, CURLINFO_TEXT, buffer, len);
}
}
static struct Curl_cftype *cf_types[] = {
&Curl_cft_tcp,
&Curl_cft_udp,
&Curl_cft_unix,
&Curl_cft_tcp_accept,
&Curl_cft_happy_eyeballs,
&Curl_cft_setup,
#ifdef USE_NGHTTP2
&Curl_cft_nghttp2,
#endif
#ifdef USE_SSL
&Curl_cft_ssl,
&Curl_cft_ssl_proxy,
#endif
#if !defined(CURL_DISABLE_PROXY)
#if !defined(CURL_DISABLE_HTTP)
&Curl_cft_http_proxy,
#endif /* !CURL_DISABLE_HTTP */
&Curl_cft_haproxy,
&Curl_cft_socks_proxy,
#endif /* !CURL_DISABLE_PROXY */
#ifdef ENABLE_QUIC
&Curl_cft_http3,
#endif
#if !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER)
&Curl_cft_http_connect,
#endif
NULL,
};
#ifndef ARRAYSIZE
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
#endif
CURLcode Curl_log_init(void)
{
const char *setting = getenv("CURL_DEBUG");
if(setting) {
char *token, *tok_buf, *tmp;
size_t i;
tmp = strdup(setting);
if(!tmp)
return CURLE_OUT_OF_MEMORY;
token = strtok_r(tmp, ", ", &tok_buf);
while(token) {
for(i = 0; cf_types[i]; ++i) {
if(strcasecompare(token, cf_types[i]->name)) {
cf_types[i]->log_level = CURL_LOG_DEBUG;
break;
}
}
token = strtok_r(NULL, ", ", &tok_buf);
}
free(tmp);
}
return CURLE_OK;
}
#else /* DEBUGBUILD */
CURLcode Curl_log_init(void)
{
return CURLE_OK;
}
#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
void Curl_log_cf_debug(struct Curl_easy *data, struct Curl_cfilter *cf,
const char *fmt, ...)
{
(void)data;
(void)cf;
(void)fmt;
}
#endif
#endif /* !DEBUGBUILD */

View file

@ -0,0 +1,138 @@
#ifndef HEADER_CURL_LOG_H
#define HEADER_CURL_LOG_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
struct Curl_easy;
struct Curl_cfilter;
/**
* Init logging, return != 0 on failure.
*/
CURLcode Curl_log_init(void);
void Curl_infof(struct Curl_easy *, const char *fmt, ...);
void Curl_failf(struct Curl_easy *, const char *fmt, ...);
#if defined(CURL_DISABLE_VERBOSE_STRINGS)
#if defined(HAVE_VARIADIC_MACROS_C99)
#define infof(...) Curl_nop_stmt
#elif defined(HAVE_VARIADIC_MACROS_GCC)
#define infof(x...) Curl_nop_stmt
#else
#error "missing VARIADIC macro define, fix and rebuild!"
#endif
#else /* CURL_DISABLE_VERBOSE_STRINGS */
#define infof Curl_infof
#endif /* CURL_DISABLE_VERBOSE_STRINGS */
#define failf Curl_failf
#define CURL_LOG_DEFAULT 0
#define CURL_LOG_DEBUG 1
#define CURL_LOG_TRACE 2
/* the function used to output verbose information */
void Curl_debug(struct Curl_easy *data, curl_infotype type,
char *ptr, size_t size);
#ifdef DEBUGBUILD
/* explainer: we have some mix configuration and werror settings
* that define HAVE_VARIADIC_MACROS_C99 even though C89 is enforced
* on gnuc and some other compiler. Need to treat carefully.
*/
#if defined(HAVE_VARIADIC_MACROS_C99) && \
defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
#define LOG_CF(data, cf, ...) \
do { if(Curl_log_cf_is_debug(cf)) \
Curl_log_cf_debug(data, cf, __VA_ARGS__); } while(0)
#else
#define LOG_CF Curl_log_cf_debug
#endif
void Curl_log_cf_debug(struct Curl_easy *data, struct Curl_cfilter *cf,
#if defined(__GNUC__) && !defined(printf) && \
defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
!defined(__MINGW32__)
const char *fmt, ...)
__attribute__((format(printf, 3, 4)));
#else
const char *fmt, ...);
#endif
#define Curl_log_cf_is_debug(cf) \
((cf) && (cf)->cft->log_level >= CURL_LOG_DEBUG)
#else /* !DEBUGBUILD */
#if defined(HAVE_VARIADIC_MACROS_C99) && \
defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
#define LOG_CF(...) Curl_nop_stmt
#define Curl_log_cf_debug(...) Curl_nop_stmt
#elif defined(HAVE_VARIADIC_MACROS_GCC) && \
defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
#define LOG_CF(x...) Curl_nop_stmt
#define Curl_log_cf_debug(x...) Curl_nop_stmt
#else
#define LOG_CF Curl_log_cf_debug
/* without c99, we seem unable to completely define away this function. */
void Curl_log_cf_debug(struct Curl_easy *data, struct Curl_cfilter *cf,
const char *fmt, ...);
#endif
#define Curl_log_cf_is_debug(x) ((void)(x), FALSE)
#endif /* !DEBUGBUILD */
#define LOG_CF_IS_DEBUG(x) Curl_log_cf_is_debug(x)
/* Macros intended for DEBUGF logging, use like:
* DEBUGF(infof(data, CFMSG(cf, "this filter %s rocks"), "very much"));
* and it will output:
* [CONN-1-0][CF-SSL] this filter very much rocks
* on connection #1 with sockindex 0 for filter of type "SSL". */
#define DMSG(d,msg) \
"[CONN-%ld] "msg, (d)->conn->connection_id
#define DMSGI(d,i,msg) \
"[CONN-%ld-%d] "msg, (d)->conn->connection_id, (i)
#define CMSG(c,msg) \
"[CONN-%ld] "msg, (c)->connection_id
#define CMSGI(c,i,msg) \
"[CONN-%ld-%d] "msg, (c)->connection_id, (i)
#define CFMSG(cf,msg) \
"[CONN-%ld-%d][CF-%s] "msg, (cf)->conn->connection_id, \
(cf)->sockindex, (cf)->cft->name
#endif /* HEADER_CURL_LOG_H */

View file

@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -20,18 +20,19 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#include "curl_setup.h" #include "curl_setup.h"
#if defined(USE_NSS) || defined(USE_OS400CRYPTO) || \ #if !defined(CURL_DISABLE_CRYPTO_AUTH)
(defined(USE_OPENSSL) && defined(OPENSSL_NO_MD4)) || \
(defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C))
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) || void Curl_md4it(unsigned char *output, const unsigned char *input,
(defined(USE_OPENSSL) && defined(OPENSSL_NO_MD4)) || const size_t len);
(defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C)) */
#endif /* !defined(CURL_DISABLE_CRYPTO_AUTH) */
#endif /* HEADER_CURL_MD4_H */ #endif /* HEADER_CURL_MD4_H */

View file

@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#ifndef CURL_DISABLE_CRYPTO_AUTH #ifndef CURL_DISABLE_CRYPTO_AUTH
@ -27,36 +29,36 @@
#define MD5_DIGEST_LEN 16 #define MD5_DIGEST_LEN 16
typedef void (* Curl_MD5_init_func)(void *context); typedef CURLcode (* Curl_MD5_init_func)(void *context);
typedef void (* Curl_MD5_update_func)(void *context, typedef void (* Curl_MD5_update_func)(void *context,
const unsigned char *data, const unsigned char *data,
unsigned int len); unsigned int len);
typedef void (* Curl_MD5_final_func)(unsigned char *result, void *context); typedef void (* Curl_MD5_final_func)(unsigned char *result, void *context);
typedef struct { struct MD5_params {
Curl_MD5_init_func md5_init_func; /* Initialize context procedure */ Curl_MD5_init_func md5_init_func; /* Initialize context procedure */
Curl_MD5_update_func md5_update_func; /* Update context with data */ Curl_MD5_update_func md5_update_func; /* Update context with data */
Curl_MD5_final_func md5_final_func; /* Get final result procedure */ Curl_MD5_final_func md5_final_func; /* Get final result procedure */
unsigned int md5_ctxtsize; /* Context structure size */ unsigned int md5_ctxtsize; /* Context structure size */
unsigned int md5_resultlen; /* Result length (bytes) */ unsigned int md5_resultlen; /* Result length (bytes) */
} MD5_params; };
typedef struct { struct MD5_context {
const MD5_params *md5_hash; /* Hash function definition */ const struct MD5_params *md5_hash; /* Hash function definition */
void *md5_hashctx; /* Hash function context */ void *md5_hashctx; /* Hash function context */
} MD5_context; };
extern const MD5_params Curl_DIGEST_MD5[1]; extern const struct MD5_params Curl_DIGEST_MD5[1];
extern const HMAC_params Curl_HMAC_MD5[1]; extern const struct HMAC_params Curl_HMAC_MD5[1];
void Curl_md5it(unsigned char *output, CURLcode Curl_md5it(unsigned char *output, const unsigned char *input,
const unsigned char *input); const size_t len);
MD5_context * Curl_MD5_init(const MD5_params *md5params); struct MD5_context *Curl_MD5_init(const struct MD5_params *md5params);
CURLcode Curl_MD5_update(MD5_context *context, CURLcode Curl_MD5_update(struct MD5_context *context,
const unsigned char *data, const unsigned char *data,
unsigned int len); unsigned int len);
CURLcode Curl_MD5_final(MD5_context *context, unsigned char *result); CURLcode Curl_MD5_final(struct MD5_context *context, unsigned char *result);
#endif #endif

View file

@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
/* /*

View file

@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -18,6 +18,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#include "curl_setup.h" #include "curl_setup.h"

View file

@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -20,6 +20,8 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#include "curl_setup.h" #include "curl_setup.h"

View file

@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -18,26 +18,29 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
/*
* This file is 'mem-include-scan' clean, which means memdebug.h and
* curl_memory.h are purposely not included in this file. See test 1132.
*
* The functions in this file are curlx functions which are not tracked by the
* curl memory tracker memdebug.
*/
#include "curl_setup.h" #include "curl_setup.h"
#include <curl/curl.h> #if defined(WIN32)
#if defined(USE_WIN32_IDN) || ((defined(USE_WINDOWS_SSPI) || \
defined(USE_WIN32_LDAP)) && defined(UNICODE))
/*
* MultiByte conversions using Windows kernel32 library.
*/
#include "curl_multibyte.h" #include "curl_multibyte.h"
#include "curl_memory.h"
/* The last #include file should be: */ /*
#include "memdebug.h" * MultiByte conversions using Windows kernel32 library.
*/
wchar_t *Curl_convert_UTF8_to_wchar(const char *str_utf8) wchar_t *curlx_convert_UTF8_to_wchar(const char *str_utf8)
{ {
wchar_t *str_w = NULL; wchar_t *str_w = NULL;
@ -59,7 +62,7 @@ wchar_t *Curl_convert_UTF8_to_wchar(const char *str_utf8)
return str_w; return str_w;
} }
char *Curl_convert_wchar_to_UTF8(const wchar_t *str_w) char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w)
{ {
char *str_utf8 = NULL; char *str_utf8 = NULL;
@ -81,4 +84,96 @@ char *Curl_convert_wchar_to_UTF8(const wchar_t *str_w)
return str_utf8; return str_utf8;
} }
#endif /* USE_WIN32_IDN || ((USE_WINDOWS_SSPI || USE_WIN32_LDAP) && UNICODE) */ #endif /* WIN32 */
#if defined(USE_WIN32_LARGE_FILES) || defined(USE_WIN32_SMALL_FILES)
int curlx_win32_open(const char *filename, int oflag, ...)
{
int pmode = 0;
#ifdef _UNICODE
int result = -1;
wchar_t *filename_w = curlx_convert_UTF8_to_wchar(filename);
#endif
va_list param;
va_start(param, oflag);
if(oflag & O_CREAT)
pmode = va_arg(param, int);
va_end(param);
#ifdef _UNICODE
if(filename_w) {
result = _wopen(filename_w, oflag, pmode);
curlx_unicodefree(filename_w);
}
else
errno = EINVAL;
return result;
#else
return (_open)(filename, oflag, pmode);
#endif
}
FILE *curlx_win32_fopen(const char *filename, const char *mode)
{
#ifdef _UNICODE
FILE *result = NULL;
wchar_t *filename_w = curlx_convert_UTF8_to_wchar(filename);
wchar_t *mode_w = curlx_convert_UTF8_to_wchar(mode);
if(filename_w && mode_w)
result = _wfopen(filename_w, mode_w);
else
errno = EINVAL;
curlx_unicodefree(filename_w);
curlx_unicodefree(mode_w);
return result;
#else
return (fopen)(filename, mode);
#endif
}
int curlx_win32_stat(const char *path, struct_stat *buffer)
{
#ifdef _UNICODE
int result = -1;
wchar_t *path_w = curlx_convert_UTF8_to_wchar(path);
if(path_w) {
#if defined(USE_WIN32_SMALL_FILES)
result = _wstat(path_w, buffer);
#else
result = _wstati64(path_w, buffer);
#endif
curlx_unicodefree(path_w);
}
else
errno = EINVAL;
return result;
#else
#if defined(USE_WIN32_SMALL_FILES)
return _stat(path, buffer);
#else
return _stati64(path, buffer);
#endif
#endif
}
int curlx_win32_access(const char *path, int mode)
{
#if defined(_UNICODE)
int result = -1;
wchar_t *path_w = curlx_convert_UTF8_to_wchar(path);
if(path_w) {
result = _waccess(path_w, mode);
curlx_unicodefree(path_w);
}
else
errno = EINVAL;
return result;
#else
return _access(path, mode);
#endif
}
#endif /* USE_WIN32_LARGE_FILES || USE_WIN32_SMALL_FILES */

View file

@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -20,49 +20,44 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#include "curl_setup.h" #include "curl_setup.h"
#if defined(USE_WIN32_IDN) || ((defined(USE_WINDOWS_SSPI) || \ #if defined(WIN32)
defined(USE_WIN32_LDAP)) && defined(UNICODE))
/* /*
* MultiByte conversions using Windows kernel32 library. * MultiByte conversions using Windows kernel32 library.
*/ */
wchar_t *Curl_convert_UTF8_to_wchar(const char *str_utf8); wchar_t *curlx_convert_UTF8_to_wchar(const char *str_utf8);
char *Curl_convert_wchar_to_UTF8(const wchar_t *str_w); char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w);
#endif /* WIN32 */
#endif /* USE_WIN32_IDN || ((USE_WINDOWS_SSPI || USE_WIN32_LDAP) && UNICODE) */
#if defined(USE_WIN32_IDN) || defined(USE_WINDOWS_SSPI) || \
defined(USE_WIN32_LDAP)
/* /*
* Macros Curl_convert_UTF8_to_tchar(), Curl_convert_tchar_to_UTF8() * Macros curlx_convert_UTF8_to_tchar(), curlx_convert_tchar_to_UTF8()
* and Curl_unicodefree() main purpose is to minimize the number of * and curlx_unicodefree() main purpose is to minimize the number of
* preprocessor conditional directives needed by code using these * preprocessor conditional directives needed by code using these
* to differentiate UNICODE from non-UNICODE builds. * to differentiate UNICODE from non-UNICODE builds.
* *
* When building with UNICODE defined, this two macros * In the case of a non-UNICODE build the tchar strings are char strings that
* Curl_convert_UTF8_to_tchar() and Curl_convert_tchar_to_UTF8() * are duplicated via strdup and remain in whatever the passed in encoding is,
* return a pointer to a newly allocated memory area holding result. * which is assumed to be UTF-8 but may be other encoding. Therefore the
* When the result is no longer needed, allocated memory is intended * significance of the conversion functions is primarily for UNICODE builds.
* to be free'ed with Curl_unicodefree().
* *
* When building without UNICODE defined, this macros * Allocated memory should be free'd with curlx_unicodefree().
* Curl_convert_UTF8_to_tchar() and Curl_convert_tchar_to_UTF8() *
* return the pointer received as argument. Curl_unicodefree() does * Note: Because these are curlx functions their memory usage is not tracked
* no actual free'ing of this pointer it is simply set to NULL. * by the curl memory tracker memdebug. You'll notice that curlx function-like
* macros call free and strdup in parentheses, eg (strdup)(ptr), and that's to
* ensure that the curl memdebug override macros do not replace them.
*/ */
#ifdef UNICODE #if defined(UNICODE) && defined(WIN32)
#define Curl_convert_UTF8_to_tchar(ptr) Curl_convert_UTF8_to_wchar((ptr)) #define curlx_convert_UTF8_to_tchar(ptr) curlx_convert_UTF8_to_wchar((ptr))
#define Curl_convert_tchar_to_UTF8(ptr) Curl_convert_wchar_to_UTF8((ptr)) #define curlx_convert_tchar_to_UTF8(ptr) curlx_convert_wchar_to_UTF8((ptr))
#define Curl_unicodefree(ptr) \
do {if((ptr)) {free((ptr)); (ptr) = NULL;}} WHILE_FALSE
typedef union { typedef union {
unsigned short *tchar_ptr; unsigned short *tchar_ptr;
@ -73,10 +68,8 @@ typedef union {
#else #else
#define Curl_convert_UTF8_to_tchar(ptr) (ptr) #define curlx_convert_UTF8_to_tchar(ptr) (strdup)(ptr)
#define Curl_convert_tchar_to_UTF8(ptr) (ptr) #define curlx_convert_tchar_to_UTF8(ptr) (strdup)(ptr)
#define Curl_unicodefree(ptr) \
do {(ptr) = NULL;} WHILE_FALSE
typedef union { typedef union {
char *tchar_ptr; char *tchar_ptr;
@ -85,8 +78,14 @@ typedef union {
const unsigned char *const_tbyte_ptr; const unsigned char *const_tbyte_ptr;
} xcharp_u; } xcharp_u;
#endif /* UNICODE */ #endif /* UNICODE && WIN32 */
#endif /* USE_WIN32_IDN || USE_WINDOWS_SSPI || USE_WIN32_LDAP */ #define curlx_unicodefree(ptr) \
do { \
if(ptr) { \
(free)(ptr); \
(ptr) = NULL; \
} \
} while(0)
#endif /* HEADER_CURL_MULTIBYTE_H */ #endif /* HEADER_CURL_MULTIBYTE_H */

View file

@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -18,23 +18,25 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#include "curl_setup.h" #include "curl_setup.h"
#if defined(USE_NTLM) #if defined(USE_CURL_NTLM_CORE)
/* /*
* NTLM details: * NTLM details:
* *
* https://davenport.sourceforge.io/ntlm.html * https://davenport.sourceforge.net/ntlm.html
* https://www.innovation.ch/java/ntlm.html * https://www.innovation.ch/java/ntlm.html
*/ */
/* Please keep the SSL backend-specific #if branches in this order: /* Please keep the SSL backend-specific #if branches in this order:
1. USE_OPENSSL 1. USE_OPENSSL
2. USE_GNUTLS_NETTLE 2. USE_WOLFSSL
3. USE_GNUTLS 3. USE_GNUTLS
4. USE_NSS 4. USE_NSS
5. USE_MBEDTLS 5. USE_MBEDTLS
@ -50,20 +52,30 @@
in NTLM type-3 messages. in NTLM type-3 messages.
*/ */
#if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO) #if defined(USE_OPENSSL)
#include <openssl/opensslconf.h>
#if !defined(OPENSSL_NO_DES) && !defined(OPENSSL_NO_DEPRECATED_3_0)
#define USE_OPENSSL_DES
#endif
#endif
#ifdef USE_OPENSSL #if defined(USE_OPENSSL_DES) || defined(USE_WOLFSSL)
#if defined(USE_OPENSSL)
# include <openssl/des.h> # include <openssl/des.h>
# ifndef OPENSSL_NO_MD4
# include <openssl/md4.h>
# else
# include "curl_md4.h"
# endif
# include <openssl/md5.h> # include <openssl/md5.h>
# include <openssl/ssl.h> # include <openssl/ssl.h>
# include <openssl/rand.h> # include <openssl/rand.h>
# if (OPENSSL_VERSION_NUMBER < 0x00907001L) #else
# include <wolfssl/options.h>
# include <wolfssl/openssl/des.h>
# include <wolfssl/openssl/md5.h>
# include <wolfssl/openssl/ssl.h>
# include <wolfssl/openssl/rand.h>
#endif
# if (defined(OPENSSL_VERSION_NUMBER) && \
(OPENSSL_VERSION_NUMBER < 0x00907001L)) && !defined(USE_WOLFSSL)
# define DES_key_schedule des_key_schedule # define DES_key_schedule des_key_schedule
# define DES_cblock des_cblock # define DES_cblock des_cblock
# define DES_set_odd_parity des_set_odd_parity # define DES_set_odd_parity des_set_odd_parity
@ -76,32 +88,19 @@
# define DESKEY(x) &x # define DESKEY(x) &x
# endif # endif
#elif defined(USE_GNUTLS_NETTLE)
# include <nettle/des.h>
# include <nettle/md4.h>
#elif defined(USE_GNUTLS) #elif defined(USE_GNUTLS)
# include <gcrypt.h> # include <nettle/des.h>
# define MD5_DIGEST_LENGTH 16
# define MD4_DIGEST_LENGTH 16
#elif defined(USE_NSS) #elif defined(USE_NSS)
# include <nss.h> # include <nss.h>
# include <pk11pub.h> # include <pk11pub.h>
# include <hasht.h> # include <hasht.h>
# include "curl_md4.h"
# define MD5_DIGEST_LENGTH MD5_LENGTH
#elif defined(USE_MBEDTLS) #elif defined(USE_MBEDTLS)
# include <mbedtls/des.h> # include <mbedtls/des.h>
# include <mbedtls/md4.h>
# if !defined(MBEDTLS_MD4_C)
# include "curl_md4.h"
# endif
#elif defined(USE_SECTRANSP) #elif defined(USE_SECTRANSP)
@ -110,15 +109,13 @@
#elif defined(USE_OS400CRYPTO) #elif defined(USE_OS400CRYPTO)
# include "cipher.mih" /* mih/cipher */ # include "cipher.mih" /* mih/cipher */
# include "curl_md4.h"
#elif defined(USE_WIN32_CRYPTO) #elif defined(USE_WIN32_CRYPTO)
# include <wincrypt.h> # include <wincrypt.h>
#else #else
# error "Can't compile NTLM support without a crypto library." # error "Can't compile NTLM support without a crypto library with DES."
#endif #endif
#include "urldata.h" #include "urldata.h"
#include "non-ascii.h"
#include "strcase.h" #include "strcase.h"
#include "curl_ntlm_core.h" #include "curl_ntlm_core.h"
#include "curl_md5.h" #include "curl_md5.h"
@ -126,12 +123,12 @@
#include "warnless.h" #include "warnless.h"
#include "curl_endian.h" #include "curl_endian.h"
#include "curl_des.h" #include "curl_des.h"
#include "curl_md4.h"
/* The last 3 #include files should be in this order */ /* The last 3 #include files should be in this order */
#include "curl_printf.h" #include "curl_printf.h"
#include "curl_memory.h" #include "curl_memory.h"
#include "memdebug.h" #include "memdebug.h"
#define NTLM_HMAC_MD5_LEN (16)
#define NTLMv2_BLOB_SIGNATURE "\x01\x01\x00\x00" #define NTLMv2_BLOB_SIGNATURE "\x01\x01\x00\x00"
#define NTLMv2_BLOB_LEN (44 -16 + ntlm->target_info_len + 4) #define NTLMv2_BLOB_LEN (44 -16 + ntlm->target_info_len + 4)
@ -150,7 +147,7 @@ static void extend_key_56_to_64(const unsigned char *key_56, char *key)
key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF); key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF);
} }
#ifdef USE_OPENSSL #if defined(USE_OPENSSL_DES) || defined(USE_WOLFSSL)
/* /*
* Turns a 56 bit key into the 64 bit, odd parity key and sets the key. The * Turns a 56 bit key into the 64 bit, odd parity key and sets the key. The
* key schedule ks is also set. * key schedule ks is also set.
@ -167,10 +164,10 @@ static void setup_des_key(const unsigned char *key_56,
DES_set_odd_parity(&key); DES_set_odd_parity(&key);
/* Set the key */ /* Set the key */
DES_set_key(&key, ks); DES_set_key_unchecked(&key, ks);
} }
#elif defined(USE_GNUTLS_NETTLE) #elif defined(USE_GNUTLS)
static void setup_des_key(const unsigned char *key_56, static void setup_des_key(const unsigned char *key_56,
struct des_ctx *des) struct des_ctx *des)
@ -187,38 +184,17 @@ static void setup_des_key(const unsigned char *key_56,
des_set_key(des, (const uint8_t *) key); des_set_key(des, (const uint8_t *) key);
} }
#elif defined(USE_GNUTLS)
/*
* Turns a 56 bit key into the 64 bit, odd parity key and sets the key.
*/
static void setup_des_key(const unsigned char *key_56,
gcry_cipher_hd_t *des)
{
char key[8];
/* Expand the 56-bit key to 64-bits */
extend_key_56_to_64(key_56, key);
/* Set the key parity to odd */
Curl_des_set_odd_parity((unsigned char *) key, sizeof(key));
/* Set the key */
gcry_cipher_setkey(*des, key, sizeof(key));
}
#elif defined(USE_NSS) #elif defined(USE_NSS)
/* /*
* Expands a 56 bit key KEY_56 to 64 bit and encrypts 64 bit of data, using * encrypt_des() expands a 56 bit key KEY_56 to 64 bit and encrypts 64 bit of
* the expanded key. The caller is responsible for giving 64 bit of valid * data, using the expanded key. IN should point to 64 bits of source data,
* data is IN and (at least) 64 bit large buffer as OUT. * OUT to a 64 bit output buffer.
*/ */
static bool encrypt_des(const unsigned char *in, unsigned char *out, static bool encrypt_des(const unsigned char *in, unsigned char *out,
const unsigned char *key_56) const unsigned char *key_56)
{ {
const CK_MECHANISM_TYPE mech = CKM_DES_ECB; /* DES cipher in ECB mode */ const CK_MECHANISM_TYPE mech = CKM_DES_ECB; /* DES cipher in ECB mode */
PK11SlotInfo *slot = NULL;
char key[8]; /* expanded 64 bit key */ char key[8]; /* expanded 64 bit key */
SECItem key_item; SECItem key_item;
PK11SymKey *symkey = NULL; PK11SymKey *symkey = NULL;
@ -228,7 +204,7 @@ static bool encrypt_des(const unsigned char *in, unsigned char *out,
bool rv = FALSE; bool rv = FALSE;
/* use internal slot for DES encryption (requires NSS to be initialized) */ /* use internal slot for DES encryption (requires NSS to be initialized) */
slot = PK11_GetInternalKeySlot(); PK11SlotInfo *slot = PK11_GetInternalKeySlot();
if(!slot) if(!slot)
return FALSE; return FALSE;
@ -355,7 +331,7 @@ static bool encrypt_des(const unsigned char *in, unsigned char *out,
/* Acquire the crypto provider */ /* Acquire the crypto provider */
if(!CryptAcquireContext(&hprov, NULL, NULL, PROV_RSA_FULL, if(!CryptAcquireContext(&hprov, NULL, NULL, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT)) CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
return FALSE; return FALSE;
/* Setup the key blob structure */ /* Setup the key blob structure */
@ -400,7 +376,7 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys,
const unsigned char *plaintext, const unsigned char *plaintext,
unsigned char *results) unsigned char *results)
{ {
#ifdef USE_OPENSSL #if defined(USE_OPENSSL_DES) || defined(USE_WOLFSSL)
DES_key_schedule ks; DES_key_schedule ks;
setup_des_key(keys, DESKEY(ks)); setup_des_key(keys, DESKEY(ks));
@ -414,7 +390,7 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys,
setup_des_key(keys + 14, DESKEY(ks)); setup_des_key(keys + 14, DESKEY(ks));
DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results + 16), DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results + 16),
DESKEY(ks), DES_ENCRYPT); DESKEY(ks), DES_ENCRYPT);
#elif defined(USE_GNUTLS_NETTLE) #elif defined(USE_GNUTLS)
struct des_ctx des; struct des_ctx des;
setup_des_key(keys, &des); setup_des_key(keys, &des);
des_encrypt(&des, 8, results, plaintext); des_encrypt(&des, 8, results, plaintext);
@ -422,23 +398,6 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys,
des_encrypt(&des, 8, results + 8, plaintext); des_encrypt(&des, 8, results + 8, plaintext);
setup_des_key(keys + 14, &des); setup_des_key(keys + 14, &des);
des_encrypt(&des, 8, results + 16, plaintext); des_encrypt(&des, 8, results + 16, plaintext);
#elif defined(USE_GNUTLS)
gcry_cipher_hd_t des;
gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
setup_des_key(keys, &des);
gcry_cipher_encrypt(des, results, 8, plaintext, 8);
gcry_cipher_close(des);
gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
setup_des_key(keys + 7, &des);
gcry_cipher_encrypt(des, results + 8, 8, plaintext, 8);
gcry_cipher_close(des);
gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
setup_des_key(keys + 14, &des);
gcry_cipher_encrypt(des, results + 16, 8, plaintext, 8);
gcry_cipher_close(des);
#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_SECTRANSP) \ #elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_SECTRANSP) \
|| defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
encrypt_des(plaintext, results, keys); encrypt_des(plaintext, results, keys);
@ -450,11 +409,9 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys,
/* /*
* Set up lanmanager hashed password * Set up lanmanager hashed password
*/ */
CURLcode Curl_ntlm_core_mk_lm_hash(struct Curl_easy *data, CURLcode Curl_ntlm_core_mk_lm_hash(const char *password,
const char *password,
unsigned char *lmbuffer /* 21 bytes */) unsigned char *lmbuffer /* 21 bytes */)
{ {
CURLcode result;
unsigned char pw[14]; unsigned char pw[14];
static const unsigned char magic[] = { static const unsigned char magic[] = {
0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 /* i.e. KGS!@#$% */ 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 /* i.e. KGS!@#$% */
@ -464,18 +421,10 @@ CURLcode Curl_ntlm_core_mk_lm_hash(struct Curl_easy *data,
Curl_strntoupper((char *)pw, password, len); Curl_strntoupper((char *)pw, password, len);
memset(&pw[len], 0, 14 - len); memset(&pw[len], 0, 14 - len);
/*
* The LanManager hashed password needs to be created using the
* password in the network encoding not the host encoding.
*/
result = Curl_convert_to_network(data, (char *)pw, 14);
if(result)
return result;
{ {
/* Create LanManager hashed password. */ /* Create LanManager hashed password. */
#ifdef USE_OPENSSL #if defined(USE_OPENSSL_DES) || defined(USE_WOLFSSL)
DES_key_schedule ks; DES_key_schedule ks;
setup_des_key(pw, DESKEY(ks)); setup_des_key(pw, DESKEY(ks));
@ -485,24 +434,12 @@ CURLcode Curl_ntlm_core_mk_lm_hash(struct Curl_easy *data,
setup_des_key(pw + 7, DESKEY(ks)); setup_des_key(pw + 7, DESKEY(ks));
DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer + 8), DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer + 8),
DESKEY(ks), DES_ENCRYPT); DESKEY(ks), DES_ENCRYPT);
#elif defined(USE_GNUTLS_NETTLE) #elif defined(USE_GNUTLS)
struct des_ctx des; struct des_ctx des;
setup_des_key(pw, &des); setup_des_key(pw, &des);
des_encrypt(&des, 8, lmbuffer, magic); des_encrypt(&des, 8, lmbuffer, magic);
setup_des_key(pw + 7, &des); setup_des_key(pw + 7, &des);
des_encrypt(&des, 8, lmbuffer + 8, magic); des_encrypt(&des, 8, lmbuffer + 8, magic);
#elif defined(USE_GNUTLS)
gcry_cipher_hd_t des;
gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
setup_des_key(pw, &des);
gcry_cipher_encrypt(des, lmbuffer, 8, magic, 8);
gcry_cipher_close(des);
gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
setup_des_key(pw + 7, &des);
gcry_cipher_encrypt(des, lmbuffer + 8, 8, magic, 8);
gcry_cipher_close(des);
#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_SECTRANSP) \ #elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_SECTRANSP) \
|| defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
encrypt_des(magic, lmbuffer, pw); encrypt_des(magic, lmbuffer, pw);
@ -515,7 +452,6 @@ CURLcode Curl_ntlm_core_mk_lm_hash(struct Curl_easy *data,
return CURLE_OK; return CURLE_OK;
} }
#ifdef USE_NTRESPONSES
static void ascii_to_unicode_le(unsigned char *dest, const char *src, static void ascii_to_unicode_le(unsigned char *dest, const char *src,
size_t srclen) size_t srclen)
{ {
@ -526,7 +462,7 @@ static void ascii_to_unicode_le(unsigned char *dest, const char *src,
} }
} }
#if defined(USE_NTLM_V2) && !defined(USE_WINDOWS_SSPI) #if !defined(USE_WINDOWS_SSPI)
static void ascii_uppercase_to_unicode_le(unsigned char *dest, static void ascii_uppercase_to_unicode_le(unsigned char *dest,
const char *src, size_t srclen) const char *src, size_t srclen)
@ -538,111 +474,84 @@ static void ascii_uppercase_to_unicode_le(unsigned char *dest,
} }
} }
#endif /* USE_NTLM_V2 && !USE_WINDOWS_SSPI */ #endif /* !USE_WINDOWS_SSPI */
/* /*
* Set up nt hashed passwords * Set up nt hashed passwords
* @unittest: 1600 * @unittest: 1600
*/ */
CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data, CURLcode Curl_ntlm_core_mk_nt_hash(const char *password,
const char *password,
unsigned char *ntbuffer /* 21 bytes */) unsigned char *ntbuffer /* 21 bytes */)
{ {
size_t len = strlen(password); size_t len = strlen(password);
unsigned char *pw; unsigned char *pw;
CURLcode result;
if(len > SIZE_T_MAX/2) /* avoid integer overflow */ if(len > SIZE_T_MAX/2) /* avoid integer overflow */
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
pw = len ? malloc(len * 2) : strdup(""); pw = len ? malloc(len * 2) : (unsigned char *)strdup("");
if(!pw) if(!pw)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
ascii_to_unicode_le(pw, password, len); ascii_to_unicode_le(pw, password, len);
/* /* Create NT hashed password. */
* The NT hashed password needs to be created using the password in the Curl_md4it(ntbuffer, pw, 2 * len);
* network encoding not the host encoding. memset(ntbuffer + 16, 0, 21 - 16);
*/
result = Curl_convert_to_network(data, (char *)pw, len * 2);
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
memset(ntbuffer + 16, 0, 21 - 16);
}
free(pw); free(pw);
return CURLE_OK; return CURLE_OK;
} }
#if defined(USE_NTLM_V2) && !defined(USE_WINDOWS_SSPI) #if !defined(USE_WINDOWS_SSPI)
/* This returns the HMAC MD5 digest */ /* Timestamp in tenths of a microsecond since January 1, 1601 00:00:00 UTC. */
static CURLcode hmac_md5(const unsigned char *key, unsigned int keylen, struct ms_filetime {
const unsigned char *data, unsigned int datalen, unsigned int dwLowDateTime;
unsigned char *output) unsigned int dwHighDateTime;
};
/* Convert a time_t to an MS FILETIME (MS-DTYP section 2.3.3). */
static void time2filetime(struct ms_filetime *ft, time_t t)
{ {
HMAC_context *ctxt = Curl_HMAC_init(Curl_HMAC_MD5, key, keylen); #if SIZEOF_TIME_T > 4
t = (t + CURL_OFF_T_C(11644473600)) * 10000000;
ft->dwLowDateTime = (unsigned int) (t & 0xFFFFFFFF);
ft->dwHighDateTime = (unsigned int) (t >> 32);
#else
unsigned int r, s;
unsigned int i;
if(!ctxt) ft->dwLowDateTime = t & 0xFFFFFFFF;
return CURLE_OUT_OF_MEMORY; ft->dwHighDateTime = 0;
/* Update the digest with the given challenge */ # ifndef HAVE_TIME_T_UNSIGNED
Curl_HMAC_update(ctxt, data, datalen); /* Extend sign if needed. */
if(ft->dwLowDateTime & 0x80000000)
ft->dwHighDateTime = ~0;
# endif
/* Finalise the digest */ /* Bias seconds to Jan 1, 1601.
Curl_HMAC_final(ctxt, output); 134774 days = 11644473600 seconds = 0x2B6109100 */
r = ft->dwLowDateTime;
ft->dwLowDateTime = (ft->dwLowDateTime + 0xB6109100U) & 0xFFFFFFFF;
ft->dwHighDateTime += ft->dwLowDateTime < r? 0x03: 0x02;
return CURLE_OK; /* Convert to tenths of microseconds. */
ft->dwHighDateTime *= 10000000;
i = 32;
do {
i -= 8;
s = ((ft->dwLowDateTime >> i) & 0xFF) * (10000000 - 1);
r = (s << i) & 0xFFFFFFFF;
s >>= 1; /* Split shift to avoid width overflow. */
s >>= 31 - i;
ft->dwLowDateTime = (ft->dwLowDateTime + r) & 0xFFFFFFFF;
if(ft->dwLowDateTime < r)
s++;
ft->dwHighDateTime += s;
} while(i);
ft->dwHighDateTime &= 0xFFFFFFFF;
#endif
} }
/* This creates the NTLMv2 hash by using NTLM hash as the key and Unicode /* This creates the NTLMv2 hash by using NTLM hash as the key and Unicode
@ -658,15 +567,11 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen,
unsigned char *identity; unsigned char *identity;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
/* we do the length checks below separately to avoid integer overflow risk if((userlen > CURL_MAX_INPUT_LENGTH) || (domlen > CURL_MAX_INPUT_LENGTH))
on extreme data lengths */
if((userlen > SIZE_T_MAX/2) ||
(domlen > SIZE_T_MAX/2) ||
((userlen + domlen) > SIZE_T_MAX/2))
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
identity_len = (userlen + domlen) * 2; identity_len = (userlen + domlen) * 2;
identity = malloc(identity_len); identity = malloc(identity_len + 1);
if(!identity) if(!identity)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
@ -674,8 +579,8 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen,
ascii_uppercase_to_unicode_le(identity, user, userlen); ascii_uppercase_to_unicode_le(identity, user, userlen);
ascii_to_unicode_le(identity + (userlen << 1), domain, domlen); ascii_to_unicode_le(identity + (userlen << 1), domain, domlen);
result = hmac_md5(ntlmhash, 16, identity, curlx_uztoui(identity_len), result = Curl_hmacit(Curl_HMAC_MD5, ntlmhash, 16, identity, identity_len,
ntlmv2hash); ntlmv2hash);
free(identity); free(identity);
return result; return result;
@ -721,26 +626,22 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
unsigned int len = 0; unsigned int len = 0;
unsigned char *ptr = NULL; unsigned char *ptr = NULL;
unsigned char hmac_output[NTLM_HMAC_MD5_LEN]; unsigned char hmac_output[HMAC_MD5_LENGTH];
curl_off_t tw; struct ms_filetime tw;
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
#if CURL_SIZEOF_CURL_OFF_T < 8
#error "this section needs 64bit support to work"
#endif
/* Calculate the timestamp */ /* Calculate the timestamp */
#ifdef DEBUGBUILD #ifdef DEBUGBUILD
char *force_timestamp = getenv("CURL_FORCETIME"); char *force_timestamp = getenv("CURL_FORCETIME");
if(force_timestamp) if(force_timestamp)
tw = CURL_OFF_T_C(11644473600) * 10000000; time2filetime(&tw, (time_t) 0);
else else
#endif #endif
tw = ((curl_off_t)time(NULL) + CURL_OFF_T_C(11644473600)) * 10000000; time2filetime(&tw, time(NULL));
/* Calculate the response len */ /* Calculate the response len */
len = NTLM_HMAC_MD5_LEN + NTLMv2_BLOB_LEN; len = HMAC_MD5_LENGTH + NTLMv2_BLOB_LEN;
/* Allocate the response */ /* Allocate the response */
ptr = calloc(1, len); ptr = calloc(1, len);
@ -748,20 +649,22 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
/* Create the BLOB structure */ /* 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" /* NTLMv2_BLOB_SIGNATURE */
"%c%c%c%c", /* Reserved = 0 */ "%c%c%c%c" /* Reserved = 0 */
"%c%c%c%c%c%c%c%c", /* Timestamp */
NTLMv2_BLOB_SIGNATURE[0], NTLMv2_BLOB_SIGNATURE[1], NTLMv2_BLOB_SIGNATURE[0], NTLMv2_BLOB_SIGNATURE[1],
NTLMv2_BLOB_SIGNATURE[2], NTLMv2_BLOB_SIGNATURE[3], NTLMv2_BLOB_SIGNATURE[2], NTLMv2_BLOB_SIGNATURE[3],
0, 0, 0, 0); 0, 0, 0, 0,
LONGQUARTET(tw.dwLowDateTime), LONGQUARTET(tw.dwHighDateTime));
Curl_write64_le(tw, ptr + 24);
memcpy(ptr + 32, challenge_client, 8); memcpy(ptr + 32, challenge_client, 8);
memcpy(ptr + 44, ntlm->target_info, ntlm->target_info_len); if(ntlm->target_info_len)
memcpy(ptr + 44, ntlm->target_info, ntlm->target_info_len);
/* Concatenate the Type 2 challenge with the BLOB and do HMAC MD5 */ /* Concatenate the Type 2 challenge with the BLOB and do HMAC MD5 */
memcpy(ptr + 8, &ntlm->nonce[0], 8); 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); NTLMv2_BLOB_LEN + 8, hmac_output);
if(result) { if(result) {
free(ptr); free(ptr);
@ -769,7 +672,7 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
} }
/* Concatenate the HMAC MD5 output with the BLOB */ /* 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 */ /* Return the response */
*ntresp = ptr; *ntresp = ptr;
@ -804,7 +707,8 @@ CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash,
memcpy(&data[0], challenge_server, 8); memcpy(&data[0], challenge_server, 8);
memcpy(&data[8], challenge_client, 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) if(result)
return result; return result;
@ -815,10 +719,6 @@ CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash,
return result; return result;
} }
#endif /* USE_NTLM_V2 && !USE_WINDOWS_SSPI */ #endif /* !USE_WINDOWS_SSPI */
#endif /* USE_NTRESPONSES */ #endif /* USE_CURL_NTLM_CORE */
#endif /* !USE_WINDOWS_SSPI || USE_WIN32_CRYPTO */
#endif /* USE_NTLM */

View file

@ -7,11 +7,11 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
* are also available at https://curl.haxx.se/docs/copyright.html. * are also available at https://curl.se/docs/copyright.html.
* *
* You may opt to use, copy, modify, merge, publish, distribute and/or sell * You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is * copies of the Software, and permit persons to whom the Software is
@ -20,59 +20,46 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied. * KIND, either express or implied.
* *
* SPDX-License-Identifier: curl
*
***************************************************************************/ ***************************************************************************/
#include "curl_setup.h" #include "curl_setup.h"
#if defined(USE_NTLM) #if defined(USE_CURL_NTLM_CORE)
/* If NSS is the first available SSL backend (see order in curl_ntlm_core.c) /* If NSS is the first available SSL backend (see order in curl_ntlm_core.c)
then it must be initialized to be used by NTLM. */ then it must be initialized to be used by NTLM. */
#if !defined(USE_OPENSSL) && \ #if !defined(USE_OPENSSL) && \
!defined(USE_GNUTLS_NETTLE) && \ !defined(USE_WOLFSSL) && \
!defined(USE_GNUTLS) && \ !defined(USE_GNUTLS) && \
defined(USE_NSS) defined(USE_NSS)
#define NTLM_NEEDS_NSS_INIT #define NTLM_NEEDS_NSS_INIT
#endif #endif
#if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO) #if defined(USE_OPENSSL)
#ifdef USE_OPENSSL
# include <openssl/ssl.h> # include <openssl/ssl.h>
#elif defined(USE_WOLFSSL)
# include <wolfssl/options.h>
# include <wolfssl/openssl/ssl.h>
#endif #endif
/* Define USE_NTRESPONSES in order to make the type-3 message include /* Helpers to generate function byte arguments in little endian order */
* the NT response message. */ #define SHORTPAIR(x) ((int)((x) & 0xff)), ((int)(((x) >> 8) & 0xff))
#define USE_NTRESPONSES #define LONGQUARTET(x) ((int)((x) & 0xff)), ((int)(((x) >> 8) & 0xff)), \
((int)(((x) >> 16) & 0xff)), ((int)(((x) >> 24) & 0xff))
/* 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)
#define USE_NTLM2SESSION
#endif
/* Define USE_NTLM_V2 in order to allow the type-3 message to include the
LMv2 and NTLMv2 response messages, requires USE_NTRESPONSES defined to 1
and support for 64-bit integers. */
#if defined(USE_NTRESPONSES) && (CURL_SIZEOF_CURL_OFF_T > 4)
#define USE_NTLM_V2
#endif
void Curl_ntlm_core_lm_resp(const unsigned char *keys, void Curl_ntlm_core_lm_resp(const unsigned char *keys,
const unsigned char *plaintext, const unsigned char *plaintext,
unsigned char *results); unsigned char *results);
CURLcode Curl_ntlm_core_mk_lm_hash(struct Curl_easy *data, CURLcode Curl_ntlm_core_mk_lm_hash(const char *password,
const char *password,
unsigned char *lmbuffer /* 21 bytes */); unsigned char *lmbuffer /* 21 bytes */);
#ifdef USE_NTRESPONSES CURLcode Curl_ntlm_core_mk_nt_hash(const char *password,
CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data,
const char *password,
unsigned char *ntbuffer /* 21 bytes */); unsigned char *ntbuffer /* 21 bytes */);
#if defined(USE_NTLM_V2) && !defined(USE_WINDOWS_SSPI) #if !defined(USE_WINDOWS_SSPI)
CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen, CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen,
const unsigned char *data, unsigned int datalen, const unsigned char *data, unsigned int datalen,
@ -94,12 +81,8 @@ CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash,
unsigned char *challenge_server, unsigned char *challenge_server,
unsigned char *lmresp); unsigned char *lmresp);
#endif /* USE_NTLM_V2 && !USE_WINDOWS_SSPI */ #endif /* !USE_WINDOWS_SSPI */
#endif /* USE_NTRESPONSES */ #endif /* USE_CURL_NTLM_CORE */
#endif /* !USE_WINDOWS_SSPI || USE_WIN32_CRYPTO */
#endif /* USE_NTLM */
#endif /* HEADER_CURL_NTLM_CORE_H */ #endif /* HEADER_CURL_NTLM_CORE_H */

Some files were not shown because too many files have changed in this diff Show more