1
0
Эх сурвалжийг харах

curl 2024-12-11 (75a2079d)

Code extracted from:

    https://github.com/curl/curl.git

at commit 75a2079d5c28debb2eaa848ca9430f1fe0d7844c (curl-8_11_1).
Curl Upstream 10 сар өмнө
parent
commit
4cebf01c70
100 өөрчлөгдсөн 2683 нэмэгдсэн , 2636 устгасан
  1. 19 33
      CMake/CurlSymbolHiding.cmake
  2. 2 19
      CMake/CurlTests.c
  3. 6 7
      CMake/FindBearSSL.cmake
  4. 7 7
      CMake/FindBrotli.cmake
  5. 22 12
      CMake/FindCares.cmake
  6. 58 22
      CMake/FindGSS.cmake
  7. 9 8
      CMake/FindLibgsasl.cmake
  8. 9 8
      CMake/FindLibidn2.cmake
  9. 6 6
      CMake/FindLibpsl.cmake
  10. 9 8
      CMake/FindLibssh.cmake
  11. 6 6
      CMake/FindLibssh2.cmake
  12. 9 8
      CMake/FindLibuv.cmake
  13. 31 35
      CMake/FindMSH3.cmake
  14. 65 67
      CMake/FindMbedTLS.cmake
  15. 6 6
      CMake/FindNGHTTP2.cmake
  16. 6 6
      CMake/FindNGHTTP3.cmake
  17. 15 10
      CMake/FindNGTCP2.cmake
  18. 9 8
      CMake/FindNettle.cmake
  19. 29 35
      CMake/FindQuiche.cmake
  20. 64 34
      CMake/FindRustls.cmake
  21. 8 7
      CMake/FindWolfSSH.cmake
  22. 47 49
      CMake/FindWolfSSL.cmake
  23. 6 8
      CMake/FindZstd.cmake
  24. 13 7
      CMake/Macros.cmake
  25. 9 33
      CMake/OtherTests.cmake
  26. 61 42
      CMake/PickyWarnings.cmake
  27. 4 5
      CMake/Platforms/WindowsCache.cmake
  28. 9 10
      CMake/curl-config.cmake.in
  29. 323 236
      CMakeLists.txt
  30. 25 19
      include/curl/curl.h
  31. 3 3
      include/curl/curlver.h
  32. 7 11
      include/curl/multi.h
  33. 25 21
      lib/CMakeLists.txt
  34. 3 3
      lib/Makefile.inc
  35. 16 18
      lib/altsvc.c
  36. 9 18
      lib/asyn-ares.c
  37. 4 4
      lib/asyn-thread.c
  38. 4 4
      lib/bufq.c
  39. 4 4
      lib/c-hyper.c
  40. 3 3
      lib/cf-h1-proxy.c
  41. 19 18
      lib/cf-h2-proxy.c
  42. 2 2
      lib/cf-haproxy.c
  43. 17 10
      lib/cf-https-connect.c
  44. 214 116
      lib/cf-socket.c
  45. 5 6
      lib/cf-socket.h
  46. 31 28
      lib/cfilters.c
  47. 12 24
      lib/conncache.c
  48. 8 8
      lib/connect.c
  49. 8 8
      lib/content_encoding.c
  50. 450 537
      lib/cookie.c
  51. 21 17
      lib/cookie.h
  52. 46 60
      lib/curl_addrinfo.c
  53. 2 0
      lib/curl_addrinfo.h
  54. 34 20
      lib/curl_config.h.cmake
  55. 3 3
      lib/curl_fnmatch.c
  56. 1 1
      lib/curl_gssapi.c
  57. 14 16
      lib/curl_hmac.h
  58. 7 7
      lib/curl_md5.h
  59. 2 0
      lib/curl_memory.h
  60. 23 11
      lib/curl_ntlm_core.c
  61. 1 1
      lib/curl_rtmp.c
  62. 33 11
      lib/curl_setup.h
  63. 1 1
      lib/curl_sha256.h
  64. 1 1
      lib/curl_sha512_256.c
  65. 3 3
      lib/curl_threads.c
  66. 1 1
      lib/curl_threads.h
  67. 7 7
      lib/curl_trc.c
  68. 11 14
      lib/curl_trc.h
  69. 0 9
      lib/curlx.h
  70. 6 7
      lib/cw-out.c
  71. 21 22
      lib/doh.c
  72. 2 2
      lib/dynhds.c
  73. 36 29
      lib/easy.c
  74. 1 1
      lib/easyif.h
  75. 8 6
      lib/escape.c
  76. 1 1
      lib/file.c
  77. 26 22
      lib/formdata.c
  78. 1 1
      lib/formdata.h
  79. 129 293
      lib/ftp.c
  80. 2 2
      lib/ftplistparser.c
  81. 2 2
      lib/getenv.c
  82. 14 11
      lib/getinfo.c
  83. 1 1
      lib/headers.c
  84. 32 38
      lib/hmac.c
  85. 13 11
      lib/hostip.c
  86. 4 0
      lib/hostip4.c
  87. 23 16
      lib/hsts.c
  88. 84 243
      lib/http.c
  89. 0 3
      lib/http.h
  90. 5 5
      lib/http1.c
  91. 103 49
      lib/http2.c
  92. 5 0
      lib/http2.h
  93. 18 31
      lib/http_aws_sigv4.c
  94. 2 2
      lib/http_chunks.c
  95. 2 2
      lib/http_digest.c
  96. 3 3
      lib/http_negotiate.c
  97. 148 5
      lib/http_proxy.c
  98. 6 0
      lib/http_proxy.h
  99. 13 13
      lib/imap.c
  100. 25 25
      lib/krb5.c

+ 19 - 33
CMake/CurlSymbolHiding.cmake

@@ -21,8 +21,6 @@
 # SPDX-License-Identifier: curl
 #
 ###########################################################################
-include(CheckCSourceCompiles)
-
 option(CURL_HIDDEN_SYMBOLS "Hide libcurl internal symbols (=hide all symbols that are not officially external)" ON)
 mark_as_advanced(CURL_HIDDEN_SYMBOLS)
 
@@ -33,48 +31,36 @@ if(WIN32 AND (ENABLE_DEBUG OR ENABLE_CURLDEBUG))
   set(CURL_HIDDEN_SYMBOLS OFF)
 endif()
 
-if(CURL_HIDDEN_SYMBOLS)
-  set(_supports_symbol_hiding FALSE)
+set(CURL_HIDES_PRIVATE_SYMBOLS FALSE)
+unset(CURL_EXTERN_SYMBOL)
+unset(CURL_CFLAG_SYMBOLS_HIDE)
 
+if(CURL_HIDDEN_SYMBOLS)
   if(CMAKE_C_COMPILER_ID MATCHES "Clang" AND NOT MSVC)
-    set(_supports_symbol_hiding TRUE)
-    set(_symbol_extern "__attribute__ ((__visibility__ (\"default\")))")
-    set(_cflag_symbols_hide "-fvisibility=hidden")
+    set(CURL_HIDES_PRIVATE_SYMBOLS TRUE)
+    set(CURL_EXTERN_SYMBOL "__attribute__((__visibility__(\"default\")))")
+    set(CURL_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
   elseif(CMAKE_COMPILER_IS_GNUCC)
     if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4)
       # Note: This is considered buggy prior to 4.0 but the autotools do not care, so let us ignore that fact
-      set(_supports_symbol_hiding TRUE)
-      set(_symbol_extern "__attribute__ ((__visibility__ (\"default\")))")
-      set(_cflag_symbols_hide "-fvisibility=hidden")
+      set(CURL_HIDES_PRIVATE_SYMBOLS TRUE)
+      set(CURL_EXTERN_SYMBOL "__attribute__((__visibility__(\"default\")))")
+      set(CURL_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
     endif()
   elseif(CMAKE_C_COMPILER_ID MATCHES "SunPro" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 8.0)
-    set(_supports_symbol_hiding TRUE)
-    set(_symbol_extern "__global")
-    set(_cflag_symbols_hide "-xldscope=hidden")
-  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 am not 100% sure
-    #       so let us do it the same way autotools do.
-    set(_supports_symbol_hiding TRUE)
-    set(_symbol_extern "__attribute__ ((__visibility__ (\"default\")))")
-    set(_cflag_symbols_hide "-fvisibility=hidden")
-    check_c_source_compiles("#include <stdio.h>
-      int main(void) { printf(\"icc fvisibility bug test\"); return 0; }" _no_bug)
-    if(NOT _no_bug)
-      set(_supports_symbol_hiding FALSE)
-      set(_symbol_extern "")
-      set(_cflag_symbols_hide "")
-    endif()
+    set(CURL_HIDES_PRIVATE_SYMBOLS TRUE)
+    set(CURL_EXTERN_SYMBOL "__global")
+    set(CURL_CFLAG_SYMBOLS_HIDE "-xldscope=hidden")
+  elseif(CMAKE_C_COMPILER_ID MATCHES "Intel" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 9.0)  # Requires 9.1.045
+    set(CURL_HIDES_PRIVATE_SYMBOLS TRUE)
+    set(CURL_EXTERN_SYMBOL "__attribute__((__visibility__(\"default\")))")
+    set(CURL_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
   elseif(MSVC)
-    set(_supports_symbol_hiding TRUE)
+    set(CURL_HIDES_PRIVATE_SYMBOLS TRUE)
   endif()
-
-  set(CURL_HIDES_PRIVATE_SYMBOLS ${_supports_symbol_hiding})
 else()
   if(MSVC)
+    # Note: This option is prone to export non-curl extra symbols.
     set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
   endif()
-  set(CURL_HIDES_PRIVATE_SYMBOLS FALSE)
 endif()
-
-set(CURL_CFLAG_SYMBOLS_HIDE ${_cflag_symbols_hide})
-set(CURL_EXTERN_SYMBOL ${_symbol_extern})

+ 2 - 19
CMake/CurlTests.c

@@ -50,6 +50,7 @@ int main(void)
   int flags = 0;
   if(0 != fcntl(0, F_SETFL, flags | O_NONBLOCK))
     return 1;
+  ;
   return 0;
 }
 #endif
@@ -159,15 +160,12 @@ int main(void) { return 0; }
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
                        && LARGE_OFF_T % 2147483647 == 1)
                       ? 1 : -1];
-int main(void) { ; return 0; }
+int main(void) { return 0; }
 #endif
 
 #ifdef HAVE_IOCTLSOCKET
 /* includes start */
 #ifdef _WIN32
-#  ifndef WIN32_LEAN_AND_MEAN
-#    define WIN32_LEAN_AND_MEAN
-#  endif
 #  include <winsock2.h>
 #endif
 int main(void)
@@ -184,9 +182,6 @@ int main(void)
 #ifdef HAVE_IOCTLSOCKET_CAMEL
 /* includes start */
 #ifdef _WIN32
-#  ifndef WIN32_LEAN_AND_MEAN
-#    define WIN32_LEAN_AND_MEAN
-#  endif
 #  include <winsock2.h>
 #endif
 int main(void)
@@ -202,9 +197,6 @@ int main(void)
 #ifdef HAVE_IOCTLSOCKET_CAMEL_FIONBIO
 /* includes start */
 #ifdef _WIN32
-#  ifndef WIN32_LEAN_AND_MEAN
-#    define WIN32_LEAN_AND_MEAN
-#  endif
 #  include <winsock2.h>
 #endif
 int main(void)
@@ -221,9 +213,6 @@ int main(void)
 #ifdef HAVE_IOCTLSOCKET_FIONBIO
 /* includes start */
 #ifdef _WIN32
-#  ifndef WIN32_LEAN_AND_MEAN
-#    define WIN32_LEAN_AND_MEAN
-#  endif
 #  include <winsock2.h>
 #endif
 int main(void)
@@ -296,9 +285,6 @@ int main(void)
 #ifdef HAVE_SETSOCKOPT_SO_NONBLOCK
 /* includes start */
 #ifdef _WIN32
-#  ifndef WIN32_LEAN_AND_MEAN
-#    define WIN32_LEAN_AND_MEAN
-#  endif
 #  include <winsock2.h>
 #endif
 /* includes start */
@@ -409,9 +395,6 @@ int main(void)
 #ifdef HAVE_WIN32_WINNT
 /* includes start */
 #ifdef _WIN32
-#  ifndef WIN32_LEAN_AND_MEAN
-#    define WIN32_LEAN_AND_MEAN
-#  endif
 #  ifndef NOGDI
 #    define NOGDI
 #  endif

+ 6 - 7
CMake/FindBearSSL.cmake

@@ -21,19 +21,18 @@
 # SPDX-License-Identifier: curl
 #
 ###########################################################################
-# Find the bearssl library
+# Find the BearSSL library
 #
 # Input variables:
 #
-# BEARSSL_INCLUDE_DIR   The bearssl include directory
-# BEARSSL_INCLUDE_DIRS  The bearssl include directory (deprecated)
-# BEARSSL_LIBRARY       Path to bearssl library
+# - `BEARSSL_INCLUDE_DIR`:   The BearSSL include directory.
+# - `BEARSSL_LIBRARY`:       Path to `bearssl` library.
 #
 # Result variables:
 #
-# BEARSSL_FOUND         System has bearssl
-# BEARSSL_INCLUDE_DIRS  The bearssl include directories
-# BEARSSL_LIBRARIES     The bearssl library names
+# - `BEARSSL_FOUND`:         System has BearSSL.
+# - `BEARSSL_INCLUDE_DIRS`:  The BearSSL include directories.
+# - `BEARSSL_LIBRARIES`:     The BearSSL library names.
 
 if(DEFINED BEARSSL_INCLUDE_DIRS AND NOT DEFINED BEARSSL_INCLUDE_DIR)
   message(WARNING "BEARSSL_INCLUDE_DIRS is deprecated, use BEARSSL_INCLUDE_DIR instead.")

+ 7 - 7
CMake/FindBrotli.cmake

@@ -25,16 +25,16 @@
 #
 # Input variables:
 #
-# BROTLI_INCLUDE_DIR   The brotli include directory
-# BROTLICOMMON_LIBRARY Path to brotlicommon library
-# BROTLIDEC_LIBRARY    Path to brotlidec library
+# - `BROTLI_INCLUDE_DIR`:    The brotli include directory.
+# - `BROTLICOMMON_LIBRARY`:  Path to `brotlicommon` library.
+# - `BROTLIDEC_LIBRARY`:     Path to `brotlidec` library.
 #
 # Result variables:
 #
-# BROTLI_FOUND         System has brotli
-# BROTLI_INCLUDE_DIRS  The brotli include directories
-# BROTLI_LIBRARIES     The brotli library names
-# BROTLI_VERSION       Version of brotli
+# - `BROTLI_FOUND`:          System has brotli.
+# - `BROTLI_INCLUDE_DIRS`:   The brotli include directories.
+# - `BROTLI_LIBRARIES`:      The brotli library names.
+# - `BROTLI_VERSION`:        Version of brotli.
 
 if(CURL_USE_PKGCONFIG)
   find_package(PkgConfig QUIET)

+ 22 - 12
CMake/FindCares.cmake

@@ -25,15 +25,15 @@
 #
 # Input variables:
 #
-# CARES_INCLUDE_DIR   The c-ares include directory
-# CARES_LIBRARY       Path to c-ares library
+# - `CARES_INCLUDE_DIR`:   The c-ares include directory.
+# - `CARES_LIBRARY`:       Path to `cares` library.
 #
 # Result variables:
 #
-# CARES_FOUND         System has c-ares
-# CARES_INCLUDE_DIRS  The c-ares include directories
-# CARES_LIBRARIES     The c-ares library names
-# CARES_VERSION       Version of c-ares
+# - `CARES_FOUND`:         System has c-ares.
+# - `CARES_INCLUDE_DIRS`:  The c-ares include directories.
+# - `CARES_LIBRARIES`:     The c-ares library names.
+# - `CARES_VERSION`:       Version of c-ares.
 
 if(CURL_USE_PKGCONFIG)
   find_package(PkgConfig QUIET)
@@ -55,12 +55,22 @@ find_library(CARES_LIBRARY NAMES ${CARES_NAMES} "cares"
 if(PC_CARES_VERSION)
   set(CARES_VERSION ${PC_CARES_VERSION})
 elseif(CARES_INCLUDE_DIR AND EXISTS "${CARES_INCLUDE_DIR}/ares_version.h")
-  set(_version_regex "#[\t ]*define[\t ]+ARES_VERSION_STR[\t ]+\"([^\"]*)\"")
-  file(STRINGS "${CARES_INCLUDE_DIR}/ares_version.h" _version_str REGEX "${_version_regex}")
-  string(REGEX REPLACE "${_version_regex}" "\\1" _version_str "${_version_str}")
-  set(CARES_VERSION "${_version_str}")
-  unset(_version_regex)
-  unset(_version_str)
+  set(_version_regex1 "#[\t ]*define[\t ]+ARES_VERSION_MAJOR[\t ]+([0-9]+).*")
+  set(_version_regex2 "#[\t ]*define[\t ]+ARES_VERSION_MINOR[\t ]+([0-9]+).*")
+  set(_version_regex3 "#[\t ]*define[\t ]+ARES_VERSION_PATCH[\t ]+([0-9]+).*")
+  file(STRINGS "${CARES_INCLUDE_DIR}/ares_version.h" _version_str1 REGEX "${_version_regex1}")
+  file(STRINGS "${CARES_INCLUDE_DIR}/ares_version.h" _version_str2 REGEX "${_version_regex2}")
+  file(STRINGS "${CARES_INCLUDE_DIR}/ares_version.h" _version_str3 REGEX "${_version_regex3}")
+  string(REGEX REPLACE "${_version_regex1}" "\\1" _version_str1 "${_version_str1}")
+  string(REGEX REPLACE "${_version_regex2}" "\\1" _version_str2 "${_version_str2}")
+  string(REGEX REPLACE "${_version_regex3}" "\\1" _version_str3 "${_version_str3}")
+  set(CARES_VERSION "${_version_str1}.${_version_str2}.${_version_str3}")
+  unset(_version_regex1)
+  unset(_version_regex2)
+  unset(_version_regex3)
+  unset(_version_str1)
+  unset(_version_str2)
+  unset(_version_str3)
 endif()
 
 include(FindPackageHandleStandardArgs)

+ 58 - 22
CMake/FindGSS.cmake

@@ -25,20 +25,21 @@
 #
 # Input variables:
 #
-# GSS_ROOT_DIR      Set this variable to the root installation of GSS
+# - `GSS_ROOT_DIR`:      Set this variable to the root installation of GSS. (also supported as environment)
 #
 # Result variables:
 #
-# GSS_FOUND         System has the Heimdal library
-# GSS_FLAVOUR       "MIT" or "Heimdal" if anything found
-# GSS_INCLUDE_DIRS  The GSS include directories
-# GSS_LIBRARIES     The GSS library names
-# GSS_LIBRARY_DIRS  The GSS library directories
-# GSS_LDFLAGS       Required linker flags
-# GSS_CFLAGS        Required compiler flags
-# GSS_VERSION       This is set to version advertised by pkg-config or read from manifest.
-#                   In case the library is found but no version info available it is set to "unknown"
+# - `GSS_FOUND`:         System has the Heimdal library.
+# - `GSS_FLAVOUR`:       "GNU", "MIT" or "Heimdal" if anything found.
+# - `GSS_INCLUDE_DIRS`:  The GSS include directories.
+# - `GSS_LIBRARIES`:     The GSS library names.
+# - `GSS_LIBRARY_DIRS`:  The GSS library directories.
+# - `GSS_PC_REQUIRES`:   The GSS pkg-config packages.
+# - `GSS_CFLAGS`:        Required compiler flags.
+# - `GSS_VERSION`:       This is set to version advertised by pkg-config or read from manifest.
+#                        In case the library is found but no version info available it is set to "unknown"
 
+set(_gnu_modname "gss")
 set(_mit_modname "mit-krb5-gssapi")
 set(_heimdal_modname "heimdal-gssapi")
 
@@ -55,7 +56,7 @@ set(_gss_root_hints
 if(NOT GSS_ROOT_DIR AND NOT "$ENV{GSS_ROOT_DIR}")
   if(CURL_USE_PKGCONFIG)
     find_package(PkgConfig QUIET)
-    pkg_search_module(_GSS ${_mit_modname} ${_heimdal_modname})
+    pkg_search_module(_GSS ${_gnu_modname} ${_mit_modname} ${_heimdal_modname})
     list(APPEND _gss_root_hints "${_GSS_PREFIX}")
   endif()
   if(WIN32)
@@ -90,7 +91,7 @@ if(NOT _GSS_FOUND)  # Not found by pkg-config. Let us take more traditional appr
       RESULT_VARIABLE _gss_configure_failed
       OUTPUT_STRIP_TRAILING_WHITESPACE
     )
-    message(STATUS "FindGSS CFLAGS: ${_GSS_CFLAGS}")
+    message(STATUS "FindGSS krb5-config --cflags: ${_GSS_CFLAGS}")
     if(NOT _gss_configure_failed)  # 0 means success
       # Should also work in an odd case when multiple directories are given
       string(STRIP "${_GSS_CFLAGS}" _GSS_CFLAGS)
@@ -113,7 +114,7 @@ if(NOT _GSS_FOUND)  # Not found by pkg-config. Let us take more traditional appr
       RESULT_VARIABLE _gss_configure_failed
       OUTPUT_STRIP_TRAILING_WHITESPACE
     )
-    message(STATUS "FindGSS LDFLAGS: ${_gss_lib_flags}")
+    message(STATUS "FindGSS krb5-config --libs: ${_gss_lib_flags}")
 
     if(NOT _gss_configure_failed)  # 0 means success
       # This script gives us libraries and link directories. Blah. We have to deal with it.
@@ -128,8 +129,6 @@ if(NOT _GSS_FOUND)  # Not found by pkg-config. Let us take more traditional appr
         elseif(_flag MATCHES "^-L.*")
           string(REGEX REPLACE "^-L" "" _val "${_flag}")
           list(APPEND _GSS_LIBRARY_DIRS "${_val}")
-        else()
-          list(APPEND _GSS_LDFLAGS "${_flag}")
         endif()
       endforeach()
     endif()
@@ -175,6 +174,7 @@ if(NOT _GSS_FOUND)  # Not found by pkg-config. Let us take more traditional appr
     )
 
     if(_GSS_INCLUDE_DIRS)  # jay, we have found something
+      cmake_push_check_state()
       set(CMAKE_REQUIRED_INCLUDES "${_GSS_INCLUDE_DIRS}")
       check_include_files("gssapi/gssapi_generic.h;gssapi/gssapi_krb5.h" _gss_have_mit_headers)
 
@@ -189,8 +189,8 @@ if(NOT _GSS_FOUND)  # Not found by pkg-config. Let us take more traditional appr
         if(_gss_have_roken_h OR _gss_have_heimdal_roken_h)
           set(GSS_FLAVOUR "Heimdal")
         endif()
-        list(REMOVE_ITEM CMAKE_REQUIRED_DEFINITIONS "-D__ROKEN_H__")
       endif()
+      cmake_pop_check_state()
     else()
       # I am not convinced if this is the right way but this is what autotools do at the moment
       find_path(_GSS_INCLUDE_DIRS NAMES "gssapi.h"
@@ -203,6 +203,18 @@ if(NOT _GSS_FOUND)  # Not found by pkg-config. Let us take more traditional appr
 
       if(_GSS_INCLUDE_DIRS)
         set(GSS_FLAVOUR "Heimdal")
+      else()
+        find_path(_GSS_INCLUDE_DIRS NAMES "gss.h"
+          HINTS
+            ${_gss_root_hints}
+          PATH_SUFFIXES
+            "include"
+        )
+
+        if(_GSS_INCLUDE_DIRS)
+          set(GSS_FLAVOUR "GNU")
+          set(GSS_PC_REQUIRES "gss")
+        endif()
       endif()
     endif()
 
@@ -216,14 +228,18 @@ if(NOT _GSS_FOUND)  # Not found by pkg-config. Let us take more traditional appr
       if(WIN32)
         if(CMAKE_SIZEOF_VOID_P EQUAL 8)
           list(APPEND _gss_libdir_suffixes "lib/AMD64")
-          if(GSS_FLAVOUR STREQUAL "MIT")
+          if(GSS_FLAVOUR STREQUAL "GNU")
+            set(_gss_libname "gss")
+          elseif(GSS_FLAVOUR STREQUAL "MIT")
             set(_gss_libname "gssapi64")
           else()
             set(_gss_libname "libgssapi")
           endif()
         else()
           list(APPEND _gss_libdir_suffixes "lib/i386")
-          if(GSS_FLAVOUR STREQUAL "MIT")
+          if(GSS_FLAVOUR STREQUAL "GNU")
+            set(_gss_libname "gss")
+          elseif(GSS_FLAVOUR STREQUAL "MIT")
             set(_gss_libname "gssapi32")
           else()
             set(_gss_libname "libgssapi")
@@ -231,7 +247,9 @@ if(NOT _GSS_FOUND)  # Not found by pkg-config. Let us take more traditional appr
         endif()
       else()
         list(APPEND _gss_libdir_suffixes "lib;lib64")  # those suffixes are not checked for HINTS
-        if(GSS_FLAVOUR STREQUAL "MIT")
+        if(GSS_FLAVOUR STREQUAL "GNU")
+          set(_gss_libname "gss")
+        elseif(GSS_FLAVOUR STREQUAL "MIT")
           set(_gss_libname "gssapi_krb5")
         else()
           set(_gss_libname "gssapi")
@@ -247,13 +265,22 @@ if(NOT _GSS_FOUND)  # Not found by pkg-config. Let us take more traditional appr
     endif()
   endif()
 else()
-  if(_GSS_MODULE_NAME STREQUAL _mit_modname OR _GSS_${_mit_modname}_VERSION)  # _GSS_MODULE_NAME set since CMake 3.16
+  # _GSS_MODULE_NAME set since CMake 3.16
+  if(_GSS_MODULE_NAME STREQUAL _gnu_modname OR _GSS_${_gnu_modname}_VERSION)
+    set(GSS_FLAVOUR "GNU")
+    set(GSS_PC_REQUIRES "gss")
+    if(NOT _GSS_VERSION)  # for old CMake versions?
+      set(_GSS_VERSION ${_GSS_${_gnu_modname}_VERSION})
+    endif()
+  elseif(_GSS_MODULE_NAME STREQUAL _mit_modname OR _GSS_${_mit_modname}_VERSION)
     set(GSS_FLAVOUR "MIT")
+    set(GSS_PC_REQUIRES "mit-krb5-gssapi")
     if(NOT _GSS_VERSION)  # for old CMake versions?
       set(_GSS_VERSION ${_GSS_${_mit_modname}_VERSION})
     endif()
   else()
     set(GSS_FLAVOUR "Heimdal")
+    set(GSS_PC_REQUIRES "heimdal-gssapi")
     if(NOT _GSS_VERSION)  # for old CMake versions?
       set(_GSS_VERSION ${_GSS_${_heimdal_modname}_VERSION})
     endif()
@@ -261,10 +288,11 @@ else()
   message(STATUS "Found GSS/${GSS_FLAVOUR} (via pkg-config): ${_GSS_INCLUDE_DIRS} (found version \"${_GSS_VERSION}\")")
 endif()
 
+string(REPLACE ";" " " _GSS_CFLAGS "${_GSS_CFLAGS}")
+
 set(GSS_INCLUDE_DIRS ${_GSS_INCLUDE_DIRS})
 set(GSS_LIBRARIES ${_GSS_LIBRARIES})
 set(GSS_LIBRARY_DIRS ${_GSS_LIBRARY_DIRS})
-set(GSS_LDFLAGS ${_GSS_LDFLAGS})
 set(GSS_CFLAGS ${_GSS_CFLAGS})
 set(GSS_VERSION ${_GSS_VERSION})
 
@@ -294,6 +322,15 @@ if(GSS_FLAVOUR)
     else()
       set(GSS_VERSION "MIT Unknown")
     endif()
+  elseif(NOT GSS_VERSION AND GSS_FLAVOUR STREQUAL "GNU")
+    if(GSS_INCLUDE_DIRS AND EXISTS "${GSS_INCLUDE_DIRS}/gss.h")
+      set(_version_regex "#[\t ]*define[\t ]+GSS_VERSION[\t ]+\"([^\"]*)\"")
+      file(STRINGS "${GSS_INCLUDE_DIRS}/gss.h" _version_str REGEX "${_version_regex}")
+      string(REGEX REPLACE "${_version_regex}" "\\1" _version_str "${_version_str}")
+      set(GSS_VERSION "${_version_str}")
+      unset(_version_regex)
+      unset(_version_str)
+    endif()
   endif()
 endif()
 
@@ -312,7 +349,6 @@ mark_as_advanced(
   _GSS_CFLAGS
   _GSS_FOUND
   _GSS_INCLUDE_DIRS
-  _GSS_LDFLAGS
   _GSS_LIBRARIES
   _GSS_LIBRARY_DIRS
   _GSS_MODULE_NAME

+ 9 - 8
CMake/FindLibgsasl.cmake

@@ -25,17 +25,17 @@
 #
 # Input variables:
 #
-# LIBGSASL_INCLUDE_DIR   The libgsasl include directory
-# LIBGSASL_LIBRARY       Path to libgsasl library
+# - `LIBGSASL_INCLUDE_DIR`:   The libgsasl include directory.
+# - `LIBGSASL_LIBRARY`:       Path to `libgsasl` library.
 #
 # Result variables:
 #
-# LIBGSASL_FOUND         System has libgsasl
-# LIBGSASL_INCLUDE_DIRS  The libgsasl include directories
-# LIBGSASL_LIBRARIES     The libgsasl library names
-# LIBGSASL_LIBRARY_DIRS  The libgsasl library directories
-# LIBGSASL_CFLAGS        Required compiler flags
-# LIBGSASL_VERSION       Version of libgsasl
+# - `LIBGSASL_FOUND`:         System has libgsasl.
+# - `LIBGSASL_INCLUDE_DIRS`:  The libgsasl include directories.
+# - `LIBGSASL_LIBRARIES`:     The libgsasl library names.
+# - `LIBGSASL_LIBRARY_DIRS`:  The libgsasl library directories.
+# - `LIBGSASL_CFLAGS`:        Required compiler flags.
+# - `LIBGSASL_VERSION`:       Version of libgsasl.
 
 if(CURL_USE_PKGCONFIG AND
    NOT DEFINED LIBGSASL_INCLUDE_DIR AND
@@ -51,6 +51,7 @@ else()
   find_path(LIBGSASL_INCLUDE_DIR NAMES "gsasl.h")
   find_library(LIBGSASL_LIBRARY NAMES "gsasl" "libgsasl")
 
+  unset(LIBGSASL_VERSION CACHE)
   if(LIBGSASL_INCLUDE_DIR AND EXISTS "${LIBGSASL_INCLUDE_DIR}/gsasl-version.h")
     set(_version_regex "#[\t ]*define[\t ]+GSASL_VERSION[\t ]+\"([^\"]*)\"")
     file(STRINGS "${LIBGSASL_INCLUDE_DIR}/gsasl-version.h" _version_str REGEX "${_version_regex}")

+ 9 - 8
CMake/FindLibidn2.cmake

@@ -25,17 +25,17 @@
 #
 # Input variables:
 #
-# LIBIDN2_INCLUDE_DIR   The libidn2 include directory
-# LIBIDN2_LIBRARY       Path to libidn2 library
+# - `LIBIDN2_INCLUDE_DIR`:   The libidn2 include directory.
+# - `LIBIDN2_LIBRARY`:       Path to `libidn2` library.
 #
 # Result variables:
 #
-# LIBIDN2_FOUND         System has libidn2
-# LIBIDN2_INCLUDE_DIRS  The libidn2 include directories
-# LIBIDN2_LIBRARIES     The libidn2 library names
-# LIBIDN2_LIBRARY_DIRS  The libidn2 library directories
-# LIBIDN2_CFLAGS        Required compiler flags
-# LIBIDN2_VERSION       Version of libidn2
+# - `LIBIDN2_FOUND`:         System has libidn2.
+# - `LIBIDN2_INCLUDE_DIRS`:  The libidn2 include directories.
+# - `LIBIDN2_LIBRARIES`:     The libidn2 library names.
+# - `LIBIDN2_LIBRARY_DIRS`:  The libidn2 library directories.
+# - `LIBIDN2_CFLAGS`:        Required compiler flags.
+# - `LIBIDN2_VERSION`:       Version of libidn2.
 
 if(CURL_USE_PKGCONFIG AND
    NOT DEFINED LIBIDN2_INCLUDE_DIR AND
@@ -51,6 +51,7 @@ else()
   find_path(LIBIDN2_INCLUDE_DIR NAMES "idn2.h")
   find_library(LIBIDN2_LIBRARY NAMES "idn2" "libidn2")
 
+  unset(LIBIDN2_VERSION CACHE)
   if(LIBIDN2_INCLUDE_DIR AND EXISTS "${LIBIDN2_INCLUDE_DIR}/idn2.h")
     set(_version_regex "#[\t ]*define[\t ]+IDN2_VERSION[\t ]+\"([^\"]*)\"")
     file(STRINGS "${LIBIDN2_INCLUDE_DIR}/idn2.h" _version_str REGEX "${_version_regex}")

+ 6 - 6
CMake/FindLibpsl.cmake

@@ -25,15 +25,15 @@
 #
 # Input variables:
 #
-# LIBPSL_INCLUDE_DIR   The libpsl include directory
-# LIBPSL_LIBRARY       Path to libpsl library
+# - `LIBPSL_INCLUDE_DIR`:   The libpsl include directory.
+# - `LIBPSL_LIBRARY`:       Path to `libpsl` library.
 #
 # Result variables:
 #
-# LIBPSL_FOUND         System has libpsl
-# LIBPSL_INCLUDE_DIRS  The libpsl include directories
-# LIBPSL_LIBRARIES     The libpsl library names
-# LIBPSL_VERSION       Version of libpsl
+# - `LIBPSL_FOUND`:         System has libpsl.
+# - `LIBPSL_INCLUDE_DIRS`:  The libpsl include directories.
+# - `LIBPSL_LIBRARIES`:     The libpsl library names.
+# - `LIBPSL_VERSION`:       Version of libpsl.
 
 if(CURL_USE_PKGCONFIG)
   find_package(PkgConfig QUIET)

+ 9 - 8
CMake/FindLibssh.cmake

@@ -25,17 +25,17 @@
 #
 # Input variables:
 #
-# LIBSSH_INCLUDE_DIR   The libssh include directory
-# LIBSSH_LIBRARY       Path to libssh library
+# LIBSSH_INCLUDE_DIR   The libssh include directory.
+# LIBSSH_LIBRARY       Path to libssh library.
 #
 # Result variables:
 #
-# LIBSSH_FOUND         System has libssh
-# LIBSSH_INCLUDE_DIRS  The libssh include directories
-# LIBSSH_LIBRARIES     The libssh library names
-# LIBSSH_LIBRARY_DIRS  The libssh library directories
-# LIBSSH_CFLAGS        Required compiler flags
-# LIBSSH_VERSION       Version of libssh
+# LIBSSH_FOUND         System has libssh.
+# LIBSSH_INCLUDE_DIRS  The libssh include directories.
+# LIBSSH_LIBRARIES     The libssh library names.
+# LIBSSH_LIBRARY_DIRS  The libssh library directories.
+# LIBSSH_CFLAGS        Required compiler flags.
+# LIBSSH_VERSION       Version of libssh.
 
 if(CURL_USE_PKGCONFIG AND
    NOT DEFINED LIBSSH_INCLUDE_DIR AND
@@ -51,6 +51,7 @@ else()
   find_path(LIBSSH_INCLUDE_DIR NAMES "libssh/libssh.h")
   find_library(LIBSSH_LIBRARY NAMES "ssh" "libssh")
 
+  unset(LIBSSH_VERSION CACHE)
   if(LIBSSH_INCLUDE_DIR AND EXISTS "${LIBSSH_INCLUDE_DIR}/libssh/libssh_version.h")
     set(_version_regex1 "#[\t ]*define[\t ]+LIBSSH_VERSION_MAJOR[\t ]+([0-9]+).*")
     set(_version_regex2 "#[\t ]*define[\t ]+LIBSSH_VERSION_MINOR[\t ]+([0-9]+).*")

+ 6 - 6
CMake/FindLibssh2.cmake

@@ -25,15 +25,15 @@
 #
 # Input variables:
 #
-# LIBSSH2_INCLUDE_DIR   The libssh2 include directory
-# LIBSSH2_LIBRARY       Path to libssh2 library
+# - `LIBSSH2_INCLUDE_DIR`:   The libssh2 include directory.
+# - `LIBSSH2_LIBRARY`:       Path to `libssh2` library.
 #
 # Result variables:
 #
-# LIBSSH2_FOUND         System has libssh2
-# LIBSSH2_INCLUDE_DIRS  The libssh2 include directories
-# LIBSSH2_LIBRARIES     The libssh2 library names
-# LIBSSH2_VERSION       Version of libssh2
+# - `LIBSSH2_FOUND`:         System has libssh2.
+# - `LIBSSH2_INCLUDE_DIRS`:  The libssh2 include directories.
+# - `LIBSSH2_LIBRARIES`:     The libssh2 library names.
+# - `LIBSSH2_VERSION`:       Version of libssh2.
 
 if(CURL_USE_PKGCONFIG)
   find_package(PkgConfig QUIET)

+ 9 - 8
CMake/FindLibuv.cmake

@@ -25,17 +25,17 @@
 #
 # Input variables:
 #
-# LIBUV_INCLUDE_DIR   The libuv include directory
-# LIBUV_LIBRARY       Path to libuv library
+# - `LIBUV_INCLUDE_DIR`:   The libuv include directory.
+# - `LIBUV_LIBRARY`:       Path to `libuv` library.
 #
 # Result variables:
 #
-# LIBUV_FOUND         System has libuv
-# LIBUV_INCLUDE_DIRS  The libuv include directories
-# LIBUV_LIBRARIES     The libuv library names
-# LIBUV_LIBRARY_DIRS  The libuv library directories
-# LIBUV_CFLAGS        Required compiler flags
-# LIBUV_VERSION       Version of libuv
+# - `LIBUV_FOUND`:         System has libuv.
+# - `LIBUV_INCLUDE_DIRS`:  The libuv include directories.
+# - `LIBUV_LIBRARIES`:     The libuv library names.
+# - `LIBUV_LIBRARY_DIRS`:  The libuv library directories.
+# - `LIBUV_CFLAGS`:        Required compiler flags.
+# - `LIBUV_VERSION`:       Version of libuv.
 
 if(CURL_USE_PKGCONFIG AND
    NOT DEFINED LIBUV_INCLUDE_DIR AND
@@ -51,6 +51,7 @@ else()
   find_path(LIBUV_INCLUDE_DIR NAMES "uv.h")
   find_library(LIBUV_LIBRARY NAMES "uv" "libuv")
 
+  unset(LIBUV_VERSION CACHE)
   if(LIBUV_INCLUDE_DIR AND EXISTS "${LIBUV_INCLUDE_DIR}/uv/version.h")
     set(_version_regex1 "#[\t ]*define[\t ]+UV_VERSION_MAJOR[\t ]+([0-9]+).*")
     set(_version_regex2 "#[\t ]*define[\t ]+UV_VERSION_MINOR[\t ]+([0-9]+).*")

+ 31 - 35
CMake/FindMSH3.cmake

@@ -25,49 +25,45 @@
 #
 # Input variables:
 #
-# MSH3_INCLUDE_DIR   The msh3 include directory
-# MSH3_LIBRARY       Path to msh3 library
+# - `MSH3_INCLUDE_DIR`:   The msh3 include directory.
+# - `MSH3_LIBRARY`:       Path to `msh3` library.
 #
 # Result variables:
 #
-# MSH3_FOUND         System has msh3
-# MSH3_INCLUDE_DIRS  The msh3 include directories
-# MSH3_LIBRARIES     The msh3 library names
-# MSH3_VERSION       Version of msh3
+# - `MSH3_FOUND`:         System has msh3.
+# - `MSH3_INCLUDE_DIRS`:  The msh3 include directories.
+# - `MSH3_LIBRARIES`:     The msh3 library names.
+# - `MSH3_LIBRARY_DIRS`:  The msh3 library directories.
+# - `MSH3_PC_REQUIRES`:   The msh3 pkg-config packages.
+# - `MSH3_CFLAGS`:        Required compiler flags.
+# - `MSH3_VERSION`:       Version of msh3.
 
-if(CURL_USE_PKGCONFIG)
+if(CURL_USE_PKGCONFIG AND
+   NOT DEFINED MSH3_INCLUDE_DIR AND
+   NOT DEFINED MSH3_LIBRARY)
   find_package(PkgConfig QUIET)
-  pkg_check_modules(PC_MSH3 "libmsh3")
+  pkg_check_modules(MSH3 "libmsh3")
 endif()
 
-find_path(MSH3_INCLUDE_DIR NAMES "msh3.h"
-  HINTS
-    ${PC_MSH3_INCLUDEDIR}
-    ${PC_MSH3_INCLUDE_DIRS}
-)
-
-find_library(MSH3_LIBRARY NAMES "msh3"
-  HINTS
-    ${PC_MSH3_LIBDIR}
-    ${PC_MSH3_LIBRARY_DIRS}
-)
+if(MSH3_FOUND)
+  set(MSH3_PC_REQUIRES "libmsh3")
+  string(REPLACE ";" " " MSH3_CFLAGS "${MSH3_CFLAGS}")
+  message(STATUS "Found MSH3 (via pkg-config): ${MSH3_INCLUDE_DIRS} (found version \"${MSH3_VERSION}\")")
+else()
+  find_path(MSH3_INCLUDE_DIR NAMES "msh3.h")
+  find_library(MSH3_LIBRARY NAMES "msh3")
 
-if(PC_MSH3_VERSION)
-  set(MSH3_VERSION ${PC_MSH3_VERSION})
-endif()
+  include(FindPackageHandleStandardArgs)
+  find_package_handle_standard_args(MSH3
+    REQUIRED_VARS
+      MSH3_INCLUDE_DIR
+      MSH3_LIBRARY
+  )
 
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(MSH3
-  REQUIRED_VARS
-    MSH3_INCLUDE_DIR
-    MSH3_LIBRARY
-  VERSION_VAR
-    MSH3_VERSION
-)
+  if(MSH3_FOUND)
+    set(MSH3_INCLUDE_DIRS ${MSH3_INCLUDE_DIR})
+    set(MSH3_LIBRARIES    ${MSH3_LIBRARY})
+  endif()
 
-if(MSH3_FOUND)
-  set(MSH3_INCLUDE_DIRS ${MSH3_INCLUDE_DIR})
-  set(MSH3_LIBRARIES    ${MSH3_LIBRARY})
+  mark_as_advanced(MSH3_INCLUDE_DIR MSH3_LIBRARY)
 endif()
-
-mark_as_advanced(MSH3_INCLUDE_DIR MSH3_LIBRARY)

+ 65 - 67
CMake/FindMbedTLS.cmake

@@ -21,22 +21,24 @@
 # SPDX-License-Identifier: curl
 #
 ###########################################################################
-# Find the mbedtls library
+# Find the mbedTLS library
 #
 # Input variables:
 #
-# MBEDTLS_INCLUDE_DIR   The mbedtls include directory
-# MBEDTLS_INCLUDE_DIRS  The mbedtls include directory (deprecated)
-# MBEDTLS_LIBRARY       Path to mbedtls library
-# MBEDX509_LIBRARY      Path to mbedx509 library
-# MBEDCRYPTO_LIBRARY    Path to mbedcrypto library
+# - `MBEDTLS_INCLUDE_DIR`:   The mbedTLS include directory.
+# - `MBEDTLS_LIBRARY`:       Path to `mbedtls` library.
+# - `MBEDX509_LIBRARY`:      Path to `mbedx509` library.
+# - `MBEDCRYPTO_LIBRARY`:    Path to `mbedcrypto` library.
 #
 # Result variables:
 #
-# MBEDTLS_FOUND         System has mbedtls
-# MBEDTLS_INCLUDE_DIRS  The mbedtls include directories
-# MBEDTLS_LIBRARIES     The mbedtls library names
-# MBEDTLS_VERSION       Version of mbedtls
+# - `MBEDTLS_FOUND`:         System has mbedTLS.
+# - `MBEDTLS_INCLUDE_DIRS`:  The mbedTLS include directories.
+# - `MBEDTLS_LIBRARIES`:     The mbedTLS library names.
+# - `MBEDTLS_LIBRARY_DIRS`:  The mbedTLS library directories.
+# - `MBEDTLS_PC_REQUIRES`:   The mbedTLS pkg-config packages.
+# - `MBEDTLS_CFLAGS`:        Required compiler flags.
+# - `MBEDTLS_VERSION`:       Version of mbedTLS.
 
 if(DEFINED MBEDTLS_INCLUDE_DIRS AND NOT DEFINED MBEDTLS_INCLUDE_DIR)
   message(WARNING "MBEDTLS_INCLUDE_DIRS is deprecated, use MBEDTLS_INCLUDE_DIR instead.")
@@ -44,68 +46,64 @@ if(DEFINED MBEDTLS_INCLUDE_DIRS AND NOT DEFINED MBEDTLS_INCLUDE_DIR)
   unset(MBEDTLS_INCLUDE_DIRS)
 endif()
 
-if(CURL_USE_PKGCONFIG)
+if(CURL_USE_PKGCONFIG AND
+   NOT DEFINED MBEDTLS_INCLUDE_DIR AND
+   NOT DEFINED MBEDTLS_LIBRARY AND
+   NOT DEFINED MBEDX509_LIBRARY AND
+   NOT DEFINED MBEDCRYPTO_LIBRARY)
   find_package(PkgConfig QUIET)
-  pkg_check_modules(PC_MBEDTLS "mbedtls")
+  pkg_check_modules(MBEDTLS "mbedtls")
+  pkg_check_modules(MBEDX509 "mbedx509")
+  pkg_check_modules(MBEDCRYPTO "mbedcrypto")
 endif()
 
-find_path(MBEDTLS_INCLUDE_DIR NAMES "mbedtls/ssl.h"
-  HINTS
-    ${PC_MBEDTLS_INCLUDEDIR}
-    ${PC_MBEDTLS_INCLUDE_DIRS}
-)
+if(MBEDTLS_FOUND AND MBEDX509_FOUND AND MBEDCRYPTO_FOUND)
+  list(APPEND MBEDTLS_LIBRARIES ${MBEDX509_LIBRARIES} ${MBEDCRYPTO_LIBRARIES})
+  list(REMOVE_DUPLICATES MBEDTLS_LIBRARIES)
+  set(MBEDTLS_PC_REQUIRES "mbedtls")
+  string(REPLACE ";" " " MBEDTLS_CFLAGS "${MBEDTLS_CFLAGS}")
+  message(STATUS "Found MbedTLS (via pkg-config): ${MBEDTLS_INCLUDE_DIRS} (found version \"${MBEDTLS_VERSION}\")")
+else()
+  find_path(MBEDTLS_INCLUDE_DIR NAMES "mbedtls/ssl.h")
+  find_library(MBEDTLS_LIBRARY NAMES "mbedtls" "libmbedtls")
+  find_library(MBEDX509_LIBRARY NAMES "mbedx509" "libmbedx509")
+  find_library(MBEDCRYPTO_LIBRARY NAMES "mbedcrypto" "libmbedcrypto")
 
-find_library(MBEDTLS_LIBRARY NAMES "mbedtls"
-  HINTS
-    ${PC_MBEDTLS_LIBDIR}
-    ${PC_MBEDTLS_LIBRARY_DIRS}
-)
-find_library(MBEDX509_LIBRARY NAMES "mbedx509"
-  HINTS
-    ${PC_MBEDTLS_LIBDIR}
-    ${PC_MBEDTLS_LIBRARY_DIRS}
-)
-find_library(MBEDCRYPTO_LIBRARY NAMES "mbedcrypto"
-  HINTS
-    ${PC_MBEDTLS_LIBDIR}
-    ${PC_MBEDTLS_LIBRARY_DIRS}
-)
-
-if(PC_MBEDTLS_VERSION)
-  set(MBEDTLS_VERSION ${PC_MBEDTLS_VERSION})
-elseif(MBEDTLS_INCLUDE_DIR)
-  if(EXISTS "${MBEDTLS_INCLUDE_DIR}/mbedtls/build_info.h")  # 3.x
-    set(_version_header "${MBEDTLS_INCLUDE_DIR}/mbedtls/build_info.h")
-  elseif(EXISTS "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h")  # 2.x
-    set(_version_header "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h")
-  else()
-    unset(_version_header)
-  endif()
-  if(_version_header)
-    set(_version_regex "#[\t ]*define[\t ]+MBEDTLS_VERSION_STRING[\t ]+\"([0-9.]+)\"")
-    file(STRINGS "${_version_header}" _version_str REGEX "${_version_regex}")
-    string(REGEX REPLACE "${_version_regex}" "\\1" _version_str "${_version_str}")
-    set(MBEDTLS_VERSION "${_version_str}")
-    unset(_version_regex)
-    unset(_version_str)
-    unset(_version_header)
+  unset(MBEDTLS_VERSION CACHE)
+  if(MBEDTLS_INCLUDE_DIR)
+    if(EXISTS "${MBEDTLS_INCLUDE_DIR}/mbedtls/build_info.h")  # 3.x
+      set(_version_header "${MBEDTLS_INCLUDE_DIR}/mbedtls/build_info.h")
+    elseif(EXISTS "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h")  # 2.x
+      set(_version_header "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h")
+    else()
+      unset(_version_header)
+    endif()
+    if(_version_header)
+      set(_version_regex "#[\t ]*define[\t ]+MBEDTLS_VERSION_STRING[\t ]+\"([0-9.]+)\"")
+      file(STRINGS "${_version_header}" _version_str REGEX "${_version_regex}")
+      string(REGEX REPLACE "${_version_regex}" "\\1" _version_str "${_version_str}")
+      set(MBEDTLS_VERSION "${_version_str}")
+      unset(_version_regex)
+      unset(_version_str)
+      unset(_version_header)
+    endif()
   endif()
-endif()
 
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(MbedTLS
-  REQUIRED_VARS
-    MBEDTLS_INCLUDE_DIR
-    MBEDTLS_LIBRARY
-    MBEDX509_LIBRARY
-    MBEDCRYPTO_LIBRARY
-  VERSION_VAR
-    MBEDTLS_VERSION
-)
+  include(FindPackageHandleStandardArgs)
+  find_package_handle_standard_args(MbedTLS
+    REQUIRED_VARS
+      MBEDTLS_INCLUDE_DIR
+      MBEDTLS_LIBRARY
+      MBEDX509_LIBRARY
+      MBEDCRYPTO_LIBRARY
+    VERSION_VAR
+      MBEDTLS_VERSION
+  )
 
-if(MBEDTLS_FOUND)
-  set(MBEDTLS_INCLUDE_DIRS ${MBEDTLS_INCLUDE_DIR})
-  set(MBEDTLS_LIBRARIES    ${MBEDTLS_LIBRARY} ${MBEDX509_LIBRARY} ${MBEDCRYPTO_LIBRARY})
-endif()
+  if(MBEDTLS_FOUND)
+    set(MBEDTLS_INCLUDE_DIRS ${MBEDTLS_INCLUDE_DIR})
+    set(MBEDTLS_LIBRARIES    ${MBEDTLS_LIBRARY} ${MBEDX509_LIBRARY} ${MBEDCRYPTO_LIBRARY})
+  endif()
 
-mark_as_advanced(MBEDTLS_INCLUDE_DIR MBEDTLS_LIBRARY MBEDX509_LIBRARY MBEDCRYPTO_LIBRARY)
+  mark_as_advanced(MBEDTLS_INCLUDE_DIR MBEDTLS_LIBRARY MBEDX509_LIBRARY MBEDCRYPTO_LIBRARY)
+endif()

+ 6 - 6
CMake/FindNGHTTP2.cmake

@@ -25,15 +25,15 @@
 #
 # Input variables:
 #
-# NGHTTP2_INCLUDE_DIR   The nghttp2 include directory
-# NGHTTP2_LIBRARY       Path to nghttp2 library
+# - `NGHTTP2_INCLUDE_DIR`:   The nghttp2 include directory.
+# - `NGHTTP2_LIBRARY`:       Path to `nghttp2` library.
 #
 # Result variables:
 #
-# NGHTTP2_FOUND         System has nghttp2
-# NGHTTP2_INCLUDE_DIRS  The nghttp2 include directories
-# NGHTTP2_LIBRARIES     The nghttp2 library names
-# NGHTTP2_VERSION       Version of nghttp2
+# - `NGHTTP2_FOUND`:         System has nghttp2.
+# - `NGHTTP2_INCLUDE_DIRS`:  The nghttp2 include directories.
+# - `NGHTTP2_LIBRARIES`:     The nghttp2 library names.
+# - `NGHTTP2_VERSION`:       Version of nghttp2.
 
 if(CURL_USE_PKGCONFIG)
   find_package(PkgConfig QUIET)

+ 6 - 6
CMake/FindNGHTTP3.cmake

@@ -25,15 +25,15 @@
 #
 # Input variables:
 #
-# NGHTTP3_INCLUDE_DIR   The nghttp3 include directory
-# NGHTTP3_LIBRARY       Path to nghttp3 library
+# - `NGHTTP3_INCLUDE_DIR`:   The nghttp3 include directory.
+# - `NGHTTP3_LIBRARY`:       Path to `nghttp3` library.
 #
 # Result variables:
 #
-# NGHTTP3_FOUND         System has nghttp3
-# NGHTTP3_INCLUDE_DIRS  The nghttp3 include directories
-# NGHTTP3_LIBRARIES     The nghttp3 library names
-# NGHTTP3_VERSION       Version of nghttp3
+# - `NGHTTP3_FOUND`:         System has nghttp3.
+# - `NGHTTP3_INCLUDE_DIRS`:  The nghttp3 include directories.
+# - `NGHTTP3_LIBRARIES`:     The nghttp3 library names.
+# - `NGHTTP3_VERSION`:       Version of nghttp3.
 
 if(CURL_USE_PKGCONFIG)
   find_package(PkgConfig QUIET)

+ 15 - 10
CMake/FindNGTCP2.cmake

@@ -26,22 +26,22 @@
 # This module accepts optional COMPONENTS to control the crypto library (these are
 # mutually exclusive):
 #
-# quictls:    Use libngtcp2_crypto_quictls   (choose this for LibreSSL)
-# BoringSSL:  Use libngtcp2_crypto_boringssl (choose this for AWS-LC)
-# wolfSSL:    Use libngtcp2_crypto_wolfssl
-# GnuTLS:     Use libngtcp2_crypto_gnutls
+# - quictls:    Use `libngtcp2_crypto_quictls`.   (choose this for LibreSSL)
+# - BoringSSL:  Use `libngtcp2_crypto_boringssl`. (choose this for AWS-LC)
+# - wolfSSL:    Use `libngtcp2_crypto_wolfssl`.
+# - GnuTLS:     Use `libngtcp2_crypto_gnutls`.
 #
 # Input variables:
 #
-# NGTCP2_INCLUDE_DIR   The ngtcp2 include directory
-# NGTCP2_LIBRARY       Path to ngtcp2 library
+# - `NGTCP2_INCLUDE_DIR`:   The ngtcp2 include directory.
+# - `NGTCP2_LIBRARY`:       Path to `ngtcp2` library.
 #
 # Result variables:
 #
-# NGTCP2_FOUND         System has ngtcp2
-# NGTCP2_INCLUDE_DIRS  The ngtcp2 include directories
-# NGTCP2_LIBRARIES     The ngtcp2 library names
-# NGTCP2_VERSION       Version of ngtcp2
+# - `NGTCP2_FOUND`:         System has ngtcp2.
+# - `NGTCP2_INCLUDE_DIRS`:  The ngtcp2 include directories.
+# - `NGTCP2_LIBRARIES`:     The ngtcp2 library names.
+# - `NGTCP2_VERSION`:       Version of ngtcp2.
 
 if(CURL_USE_PKGCONFIG)
   find_package(PkgConfig QUIET)
@@ -84,14 +84,19 @@ if(NGTCP2_FIND_COMPONENTS)
 
   if(_ngtcp2_crypto_backend)
     string(TOLOWER "ngtcp2_crypto_${_ngtcp2_crypto_backend}" _crypto_library)
+
     if(CURL_USE_PKGCONFIG)
       pkg_check_modules(PC_${_crypto_library} "lib${_crypto_library}")
     endif()
+
+    get_filename_component(_ngtcp2_library_dir "${NGTCP2_LIBRARY}" DIRECTORY)
     find_library(${_crypto_library}_LIBRARY NAMES ${_crypto_library}
       HINTS
+        ${_ngtcp2_library_dir}
         ${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})

+ 9 - 8
CMake/FindNettle.cmake

@@ -25,17 +25,17 @@
 #
 # Input variables:
 #
-# NETTLE_INCLUDE_DIR   The nettle include directory
-# NETTLE_LIBRARY       Path to nettle library
+# - `NETTLE_INCLUDE_DIR`:   The nettle include directory.
+# - `NETTLE_LIBRARY`:       Path to `nettle` library.
 #
 # Result variables:
 #
-# NETTLE_FOUND         System has nettle
-# NETTLE_INCLUDE_DIRS  The nettle include directories
-# NETTLE_LIBRARIES     The nettle library names
-# NETTLE_LIBRARY_DIRS  The nettle library directories
-# NETTLE_CFLAGS        Required compiler flags
-# NETTLE_VERSION       Version of nettle
+# - `NETTLE_FOUND`:         System has nettle.
+# - `NETTLE_INCLUDE_DIRS`:  The nettle include directories.
+# - `NETTLE_LIBRARIES`:     The nettle library names.
+# - `NETTLE_LIBRARY_DIRS`:  The nettle library directories.
+# - `NETTLE_CFLAGS`:        Required compiler flags.
+# - `NETTLE_VERSION`:       Version of nettle.
 
 if(CURL_USE_PKGCONFIG AND
    NOT DEFINED NETTLE_INCLUDE_DIR AND
@@ -51,6 +51,7 @@ else()
   find_path(NETTLE_INCLUDE_DIR NAMES "nettle/sha2.h")
   find_library(NETTLE_LIBRARY NAMES "nettle")
 
+  unset(NETTLE_VERSION CACHE)
   if(NETTLE_INCLUDE_DIR AND EXISTS "${NETTLE_INCLUDE_DIR}/nettle/version.h")
     set(_version_regex1 "#[\t ]*define[ \t]+NETTLE_VERSION_MAJOR[ \t]+([0-9]+).*")
     set(_version_regex2 "#[\t ]*define[ \t]+NETTLE_VERSION_MINOR[ \t]+([0-9]+).*")

+ 29 - 35
CMake/FindQuiche.cmake

@@ -25,49 +25,43 @@
 #
 # Input variables:
 #
-# QUICHE_INCLUDE_DIR   The quiche include directory
-# QUICHE_LIBRARY       Path to quiche library
+# - `QUICHE_INCLUDE_DIR`:   The quiche include directory.
+# - `QUICHE_LIBRARY`:       Path to `quiche` library.
 #
 # Result variables:
 #
-# QUICHE_FOUND         System has quiche
-# QUICHE_INCLUDE_DIRS  The quiche include directories
-# QUICHE_LIBRARIES     The quiche library names
-# QUICHE_VERSION       Version of quiche
+# - `QUICHE_FOUND`:         System has quiche.
+# - `QUICHE_INCLUDE_DIRS`:  The quiche include directories.
+# - `QUICHE_LIBRARIES`:     The quiche library names.
+# - `QUICHE_LIBRARY_DIRS`:  The quiche library directories.
+# - `QUICHE_CFLAGS`:        Required compiler flags.
+# - `QUICHE_VERSION`:       Version of quiche.
 
-if(CURL_USE_PKGCONFIG)
+if(CURL_USE_PKGCONFIG AND
+   NOT DEFINED QUICHE_INCLUDE_DIR AND
+   NOT DEFINED QUICHE_LIBRARY)
   find_package(PkgConfig QUIET)
-  pkg_check_modules(PC_QUICHE "quiche")
+  pkg_check_modules(QUICHE "quiche")
 endif()
 
-find_path(QUICHE_INCLUDE_DIR NAMES "quiche.h"
-  HINTS
-    ${PC_QUICHE_INCLUDEDIR}
-    ${PC_QUICHE_INCLUDE_DIRS}
-)
-
-find_library(QUICHE_LIBRARY NAMES "quiche"
-  HINTS
-    ${PC_QUICHE_LIBDIR}
-    ${PC_QUICHE_LIBRARY_DIRS}
-)
+if(QUICHE_FOUND)
+  string(REPLACE ";" " " QUICHE_CFLAGS "${QUICHE_CFLAGS}")
+  message(STATUS "Found Quiche (via pkg-config): ${QUICHE_INCLUDE_DIRS} (found version \"${QUICHE_VERSION}\")")
+else()
+  find_path(QUICHE_INCLUDE_DIR NAMES "quiche.h")
+  find_library(QUICHE_LIBRARY NAMES "quiche")
 
-if(PC_QUICHE_VERSION)
-  set(QUICHE_VERSION ${PC_QUICHE_VERSION})
-endif()
+  include(FindPackageHandleStandardArgs)
+  find_package_handle_standard_args(Quiche
+    REQUIRED_VARS
+      QUICHE_INCLUDE_DIR
+      QUICHE_LIBRARY
+  )
 
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(Quiche
-  REQUIRED_VARS
-    QUICHE_INCLUDE_DIR
-    QUICHE_LIBRARY
-  VERSION_VAR
-    QUICHE_VERSION
-)
+  if(QUICHE_FOUND)
+    set(QUICHE_INCLUDE_DIRS ${QUICHE_INCLUDE_DIR})
+    set(QUICHE_LIBRARIES    ${QUICHE_LIBRARY})
+  endif()
 
-if(QUICHE_FOUND)
-  set(QUICHE_INCLUDE_DIRS ${QUICHE_INCLUDE_DIR})
-  set(QUICHE_LIBRARIES    ${QUICHE_LIBRARY})
+  mark_as_advanced(QUICHE_INCLUDE_DIR QUICHE_LIBRARY)
 endif()
-
-mark_as_advanced(QUICHE_INCLUDE_DIR QUICHE_LIBRARY)

+ 64 - 34
CMake/FindRustls.cmake

@@ -21,53 +21,83 @@
 # SPDX-License-Identifier: curl
 #
 ###########################################################################
-# Find the rustls library
+# Find the Rustls library
 #
 # Input variables:
 #
-# RUSTLS_INCLUDE_DIR   The rustls include directory
-# RUSTLS_LIBRARY       Path to rustls library
+# - `RUSTLS_INCLUDE_DIR`:   The Rustls include directory.
+# - `RUSTLS_LIBRARY`:       Path to `rustls` library.
 #
 # Result variables:
 #
-# RUSTLS_FOUND         System has rustls
-# RUSTLS_INCLUDE_DIRS  The rustls include directories
-# RUSTLS_LIBRARIES     The rustls library names
-# RUSTLS_VERSION       Version of rustls
+# - `RUSTLS_FOUND`:         System has Rustls.
+# - `RUSTLS_INCLUDE_DIRS`:  The Rustls include directories.
+# - `RUSTLS_LIBRARIES`:     The Rustls library names.
+# - `RUSTLS_LIBRARY_DIRS`:  The Rustls library directories.
+# - `RUSTLS_PC_REQUIRES`:   The Rustls pkg-config packages.
+# - `RUSTLS_CFLAGS`:        Required compiler flags.
+# - `RUSTLS_VERSION`:       Version of Rustls.
 
-if(CURL_USE_PKGCONFIG)
+if(CURL_USE_PKGCONFIG AND
+   NOT DEFINED RUSTLS_INCLUDE_DIR AND
+   NOT DEFINED RUSTLS_LIBRARY)
   find_package(PkgConfig QUIET)
-  pkg_check_modules(PC_RUSTLS "rustls")
+  pkg_check_modules(RUSTLS "rustls")
 endif()
 
-find_path(RUSTLS_INCLUDE_DIR NAMES "rustls.h"
-  HINTS
-    ${PC_RUSTLS_INCLUDEDIR}
-    ${PC_RUSTLS_INCLUDE_DIRS}
-)
+if(RUSTLS_FOUND)
+  set(RUSTLS_PC_REQUIRES "rustls")
+  string(REPLACE ";" " " RUSTLS_CFLAGS "${RUSTLS_CFLAGS}")
+  message(STATUS "Found Rustls (via pkg-config): ${RUSTLS_INCLUDE_DIRS} (found version \"${RUSTLS_VERSION}\")")
+else()
+  find_path(RUSTLS_INCLUDE_DIR NAMES "rustls.h")
+  find_library(RUSTLS_LIBRARY NAMES "rustls")
+
+  include(FindPackageHandleStandardArgs)
+  find_package_handle_standard_args(Rustls
+    REQUIRED_VARS
+      RUSTLS_INCLUDE_DIR
+      RUSTLS_LIBRARY
+  )
 
-find_library(RUSTLS_LIBRARY NAMES "rustls"
-  HINTS
-    ${PC_RUSTLS_LIBDIR}
-    ${PC_RUSTLS_LIBRARY_DIRS}
-)
+  if(RUSTLS_FOUND)
+    set(RUSTLS_INCLUDE_DIRS ${RUSTLS_INCLUDE_DIR})
+    set(RUSTLS_LIBRARIES    ${RUSTLS_LIBRARY})
+  endif()
 
-if(PC_RUSTLS_VERSION)
-  set(RUSTLS_VERSION ${PC_RUSTLS_VERSION})
+  mark_as_advanced(RUSTLS_INCLUDE_DIR RUSTLS_LIBRARY)
 endif()
 
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(Rustls
-  REQUIRED_VARS
-    RUSTLS_INCLUDE_DIR
-    RUSTLS_LIBRARY
-  VERSION_VAR
-    RUSTLS_VERSION
-)
+if(APPLE)
+  find_library(SECURITY_FRAMEWORK "Security")
+  mark_as_advanced(SECURITY_FRAMEWORK)
+  if(NOT SECURITY_FRAMEWORK)
+    message(FATAL_ERROR "Security framework not found")
+  endif()
+  list(APPEND RUSTLS_LIBRARIES "-framework Security")
 
-if(RUSTLS_FOUND)
-  set(RUSTLS_INCLUDE_DIRS ${RUSTLS_INCLUDE_DIR})
-  set(RUSTLS_LIBRARIES    ${RUSTLS_LIBRARY})
-endif()
+  find_library(FOUNDATION_FRAMEWORK "Foundation")
+  mark_as_advanced(FOUNDATION_FRAMEWORK)
+  if(NOT FOUNDATION_FRAMEWORK)
+    message(FATAL_ERROR "Foundation framework not found")
+  endif()
+  list(APPEND RUSTLS_LIBRARIES "-framework Foundation")
+elseif(NOT WIN32)
+  find_library(_pthread_library "pthread")
+  if(_pthread_library)
+    list(APPEND RUSTLS_LIBRARIES "pthread")
+  endif()
+  mark_as_advanced(_pthread_library)
+
+  find_library(_dl_library "dl")
+  if(_dl_library)
+    list(APPEND RUSTLS_LIBRARIES "dl")
+  endif()
+  mark_as_advanced(_dl_library)
 
-mark_as_advanced(RUSTLS_INCLUDE_DIR RUSTLS_LIBRARY)
+  find_library(_math_library "m")
+  if(_math_library)
+    list(APPEND RUSTLS_LIBRARIES "m")
+  endif()
+  mark_as_advanced(_math_library)
+endif()

+ 8 - 7
CMake/FindWolfSSH.cmake

@@ -21,23 +21,24 @@
 # SPDX-License-Identifier: curl
 #
 ###########################################################################
-# Find the wolfssh library
+# Find the wolfSSH library
 #
 # Input variables:
 #
-# WOLFSSH_INCLUDE_DIR   The wolfssh include directory
-# WOLFSSH_LIBRARY       Path to wolfssh library
+# - `WOLFSSH_INCLUDE_DIR`:   The wolfSSH include directory.
+# - `WOLFSSH_LIBRARY`:       Path to `wolfssh` library.
 #
 # Result variables:
 #
-# WOLFSSH_FOUND         System has wolfssh
-# WOLFSSH_INCLUDE_DIRS  The wolfssh include directories
-# WOLFSSH_LIBRARIES     The wolfssh library names
-# WOLFSSH_VERSION       Version of wolfssh
+# - `WOLFSSH_FOUND`:         System has wolfSSH.
+# - `WOLFSSH_INCLUDE_DIRS`:  The wolfSSH include directories.
+# - `WOLFSSH_LIBRARIES`:     The wolfSSH library names.
+# - `WOLFSSH_VERSION`:       Version of wolfSSH.
 
 find_path(WOLFSSH_INCLUDE_DIR NAMES "wolfssh/ssh.h")
 find_library(WOLFSSH_LIBRARY NAMES "wolfssh" "libwolfssh")
 
+unset(WOLFSSH_VERSION CACHE)
 if(WOLFSSH_INCLUDE_DIR AND EXISTS "${WOLFSSH_INCLUDE_DIR}/wolfssh/version.h")
   set(_version_regex "#[\t ]*define[\t ]+LIBWOLFSSH_VERSION_STRING[\t ]+\"([^\"]*)\"")
   file(STRINGS "${WOLFSSH_INCLUDE_DIR}/wolfssh/version.h" _version_str REGEX "${_version_regex}")

+ 47 - 49
CMake/FindWolfSSL.cmake

@@ -21,21 +21,21 @@
 # SPDX-License-Identifier: curl
 #
 ###########################################################################
-# Find the wolfssl library
+# Find the wolfSSL library
 #
 # Input variables:
 #
-# WOLFSSL_INCLUDE_DIR   The wolfssl include directory
-# WolfSSL_INCLUDE_DIR   The wolfssl include directory (deprecated)
-# WOLFSSL_LIBRARY       Path to wolfssl library
-# WolfSSL_LIBRARY       Path to wolfssl library (deprecated)
+# - `WOLFSSL_INCLUDE_DIR`:   The wolfSSL include directory.
+# - `WOLFSSL_LIBRARY`:       Path to `wolfssl` library.
 #
 # Result variables:
 #
-# WOLFSSL_FOUND         System has wolfssl
-# WOLFSSL_INCLUDE_DIRS  The wolfssl include directories
-# WOLFSSL_LIBRARIES     The wolfssl library names
-# WOLFSSL_VERSION       Version of wolfssl
+# - `WOLFSSL_FOUND`:         System has wolfSSL.
+# - `WOLFSSL_INCLUDE_DIRS`:  The wolfSSL include directories.
+# - `WOLFSSL_LIBRARIES`:     The wolfSSL library names.
+# - `WOLFSSL_LIBRARY_DIRS`:  The wolfSSL library directories.
+# - `WOLFSSL_CFLAGS`:        Required compiler flags.
+# - `WOLFSSL_VERSION`:       Version of wolfSSL.
 
 if(DEFINED WolfSSL_INCLUDE_DIR AND NOT DEFINED WOLFSSL_INCLUDE_DIR)
   message(WARNING "WolfSSL_INCLUDE_DIR is deprecated, use WOLFSSL_INCLUDE_DIR instead.")
@@ -46,53 +46,51 @@ if(DEFINED WolfSSL_LIBRARY AND NOT DEFINED WOLFSSL_LIBRARY)
   set(WOLFSSL_LIBRARY "${WolfSSL_LIBRARY}")
 endif()
 
-if(CURL_USE_PKGCONFIG)
+if(CURL_USE_PKGCONFIG AND
+   NOT DEFINED WOLFSSL_INCLUDE_DIR AND
+   NOT DEFINED WOLFSSL_LIBRARY)
   find_package(PkgConfig QUIET)
-  pkg_check_modules(PC_WOLFSSL "wolfssl")
+  pkg_check_modules(WOLFSSL "wolfssl")
 endif()
 
-find_path(WOLFSSL_INCLUDE_DIR NAMES "wolfssl/ssl.h"
-  HINTS
-    ${PC_WOLFSSL_INCLUDEDIR}
-    ${PC_WOLFSSL_INCLUDE_DIRS}
-)
+if(WOLFSSL_FOUND)
+  string(REPLACE ";" " " WOLFSSL_CFLAGS "${WOLFSSL_CFLAGS}")
+  message(STATUS "Found WolfSSL (via pkg-config): ${WOLFSSL_INCLUDE_DIRS} (found version \"${WOLFSSL_VERSION}\")")
+else()
+  find_path(WOLFSSL_INCLUDE_DIR NAMES "wolfssl/ssl.h")
+  find_library(WOLFSSL_LIBRARY NAMES "wolfssl")
 
-find_library(WOLFSSL_LIBRARY NAMES "wolfssl"
-  HINTS
-    ${PC_WOLFSSL_LIBDIR}
-    ${PC_WOLFSSL_LIBRARY_DIRS}
-)
+  unset(WOLFSSL_VERSION CACHE)
+  if(WOLFSSL_INCLUDE_DIR AND EXISTS "${WOLFSSL_INCLUDE_DIR}/wolfssl/version.h")
+    set(_version_regex "#[\t ]*define[\t ]+LIBWOLFSSL_VERSION_STRING[\t ]+\"([^\"]*)\"")
+    file(STRINGS "${WOLFSSL_INCLUDE_DIR}/wolfssl/version.h" _version_str REGEX "${_version_regex}")
+    string(REGEX REPLACE "${_version_regex}" "\\1" _version_str "${_version_str}")
+    set(WOLFSSL_VERSION "${_version_str}")
+    unset(_version_regex)
+    unset(_version_str)
+  endif()
 
-if(PC_WOLFSSL_VERSION)
-  set(WOLFSSL_VERSION ${PC_WOLFSSL_VERSION})
-elseif(WOLFSSL_INCLUDE_DIR AND EXISTS "${WOLFSSL_INCLUDE_DIR}/wolfssl/version.h")
-  set(_version_regex "#[\t ]*define[\t ]+LIBWOLFSSL_VERSION_STRING[\t ]+\"([^\"]*)\"")
-  file(STRINGS "${WOLFSSL_INCLUDE_DIR}/wolfssl/version.h" _version_str REGEX "${_version_regex}")
-  string(REGEX REPLACE "${_version_regex}" "\\1" _version_str "${_version_str}")
-  set(WOLFSSL_VERSION "${_version_str}")
-  unset(_version_regex)
-  unset(_version_str)
-endif()
+  include(FindPackageHandleStandardArgs)
+  find_package_handle_standard_args(WolfSSL
+    REQUIRED_VARS
+      WOLFSSL_INCLUDE_DIR
+      WOLFSSL_LIBRARY
+    VERSION_VAR
+      WOLFSSL_VERSION
+  )
 
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(WolfSSL
-  REQUIRED_VARS
-    WOLFSSL_INCLUDE_DIR
-    WOLFSSL_LIBRARY
-  VERSION_VAR
-    WOLFSSL_VERSION
-)
+  if(WOLFSSL_FOUND)
+    set(WOLFSSL_INCLUDE_DIRS ${WOLFSSL_INCLUDE_DIR})
+    set(WOLFSSL_LIBRARIES    ${WOLFSSL_LIBRARY})
+  endif()
 
-if(WOLFSSL_FOUND)
-  set(WOLFSSL_INCLUDE_DIRS ${WOLFSSL_INCLUDE_DIR})
-  set(WOLFSSL_LIBRARIES    ${WOLFSSL_LIBRARY})
+  mark_as_advanced(WOLFSSL_INCLUDE_DIR WOLFSSL_LIBRARY)
+endif()
 
-  if(NOT WIN32)
-    find_library(_math_library "m")
-    if(_math_library)
-      list(APPEND WOLFSSL_LIBRARIES "m")  # for log and pow
-    endif()
+if(NOT WIN32)
+  find_library(_math_library "m")
+  if(_math_library)
+    list(APPEND WOLFSSL_LIBRARIES "m")  # for log and pow
   endif()
+  mark_as_advanced(_math_library)
 endif()
-
-mark_as_advanced(WOLFSSL_INCLUDE_DIR WOLFSSL_LIBRARY)

+ 6 - 8
CMake/FindZstd.cmake

@@ -25,17 +25,15 @@
 #
 # Input variables:
 #
-# ZSTD_INCLUDE_DIR   The zstd include directory
-# Zstd_INCLUDE_DIR   The zstd include directory (deprecated)
-# ZSTD_LIBRARY       Path to zstd library
-# Zstd_LIBRARY       Path to zstd library (deprecated)
+# - `ZSTD_INCLUDE_DIR`:   The zstd include directory.
+# - `ZSTD_LIBRARY`:       Path to `zstd` library.
 #
 # Result variables:
 #
-# ZSTD_FOUND         System has zstd
-# ZSTD_INCLUDE_DIRS  The zstd include directories
-# ZSTD_LIBRARIES     The zstd library names
-# ZSTD_VERSION       Version of zstd
+# - `ZSTD_FOUND`:         System has zstd.
+# - `ZSTD_INCLUDE_DIRS`:  The zstd include directories.
+# - `ZSTD_LIBRARIES`:     The zstd library names.
+# - `ZSTD_VERSION`:       Version of zstd.
 
 if(DEFINED Zstd_INCLUDE_DIR AND NOT DEFINED ZSTD_INCLUDE_DIR)
   message(WARNING "Zstd_INCLUDE_DIR is deprecated, use ZSTD_INCLUDE_DIR instead.")

+ 13 - 7
CMake/Macros.cmake

@@ -30,8 +30,7 @@
 macro(check_include_file_concat _file _variable)
   check_include_files("${CURL_INCLUDES};${_file}" ${_variable})
   if(${_variable})
-    set(CURL_INCLUDES ${CURL_INCLUDES} ${_file})
-    set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -D${_variable}")
+    list(APPEND CURL_INCLUDES ${_file})
   endif()
 endmacro()
 
@@ -39,8 +38,7 @@ endmacro()
 # Return result in variable: CURL_TEST_OUTPUT
 macro(curl_internal_test _curl_test)
   if(NOT DEFINED "${_curl_test}")
-    set(_macro_check_function_definitions
-      "-D${_curl_test} ${CURL_TEST_DEFINES} ${CMAKE_REQUIRED_FLAGS}")
+    string(REPLACE ";" " " _cmake_required_definitions "${CMAKE_REQUIRED_DEFINITIONS}")
     if(CMAKE_REQUIRED_LIBRARIES)
       set(_curl_test_add_libraries
         "-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}")
@@ -48,10 +46,10 @@ macro(curl_internal_test _curl_test)
 
     message(STATUS "Performing Test ${_curl_test}")
     try_compile(${_curl_test}
-      ${CMAKE_BINARY_DIR}
+      ${PROJECT_BINARY_DIR}
       "${CMAKE_CURRENT_SOURCE_DIR}/CMake/CurlTests.c"
       CMAKE_FLAGS
-        "-DCOMPILE_DEFINITIONS:STRING=${_macro_check_function_definitions}"
+        "-DCOMPILE_DEFINITIONS:STRING=-D${_curl_test} ${CURL_TEST_DEFINES} ${_cmake_required_definitions}"
         "${_curl_test_add_libraries}"
       OUTPUT_VARIABLE CURL_TEST_OUTPUT)
     if(${_curl_test})
@@ -64,7 +62,7 @@ macro(curl_internal_test _curl_test)
   endif()
 endmacro()
 
-macro(optional_dependency _dependency)
+macro(curl_dependency_option _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")
 
@@ -74,3 +72,11 @@ macro(optional_dependency _dependency)
     find_package(${_dependency} REQUIRED)
   endif()
 endmacro()
+
+# Convert the passed paths to libpath linker options and add them to CMAKE_REQUIRED_LINK_OPTIONS.
+macro(curl_required_libpaths _libpaths_arg)
+  set(_libpaths "${_libpaths_arg}")
+  foreach(_libpath IN LISTS _libpaths)
+    list(APPEND CMAKE_REQUIRED_LINK_OPTIONS "${CMAKE_LIBRARY_PATH_FLAG}${_libpath}")
+  endforeach()
+endmacro()

+ 9 - 33
CMake/OtherTests.cmake

@@ -32,20 +32,21 @@ macro(add_header_include _check _header)
   endif()
 endmacro()
 
-set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
+set(_cmake_try_compile_target_type_save ${CMAKE_TRY_COMPILE_TARGET_TYPE})
+set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")
 
 if(NOT DEFINED HAVE_STRUCT_SOCKADDR_STORAGE)
+  cmake_push_check_state()
   unset(CMAKE_EXTRA_INCLUDE_FILES)
   if(WIN32)
     set(CMAKE_EXTRA_INCLUDE_FILES "winsock2.h")
-    set(CMAKE_REQUIRED_DEFINITIONS "-DWIN32_LEAN_AND_MEAN")
     set(CMAKE_REQUIRED_LIBRARIES "ws2_32")
   elseif(HAVE_SYS_SOCKET_H)
     set(CMAKE_EXTRA_INCLUDE_FILES "sys/socket.h")
   endif()
   check_type_size("struct sockaddr_storage" SIZEOF_STRUCT_SOCKADDR_STORAGE)
   set(HAVE_STRUCT_SOCKADDR_STORAGE ${HAVE_SIZEOF_STRUCT_SOCKADDR_STORAGE})
-  set(CMAKE_EXTRA_INCLUDE_FILES "")
+  cmake_pop_check_state()
 endif()
 
 if(NOT WIN32)
@@ -74,35 +75,8 @@ check_c_source_compiles("${_source_epilogue}
     return 0;
   }" HAVE_STRUCT_TIMEVAL)
 
-unset(CMAKE_TRY_COMPILE_TARGET_TYPE)
-
-if(NOT APPLE)
-  set(_source_epilogue "#undef inline")
-  add_header_include(HAVE_SYS_POLL_H "sys/poll.h")
-  add_header_include(HAVE_POLL_H "poll.h")
-  if(NOT CMAKE_CROSSCOMPILING)
-    check_c_source_runs("${_source_epilogue}
-      #include <stdlib.h>
-      int main(void)
-      {
-        if(0 != poll(0, 0, 10)) {
-          return 1; /* fail */
-        }
-        return 0;
-      }" HAVE_POLL_FINE)
-  elseif(UNIX)
-    check_c_source_compiles("${_source_epilogue}
-      #include <stdlib.h>
-      int main(void)
-      {
-        #if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L
-          (void)poll(0, 0, 0);
-        #else
-          #error force compilation error
-        #endif
-      }" HAVE_POLL_FINE)
-  endif()
-endif()
+set(CMAKE_TRY_COMPILE_TARGET_TYPE ${_cmake_try_compile_target_type_save})
+unset(_cmake_try_compile_target_type_save)
 
 # Detect HAVE_GETADDRINFO_THREADSAFE
 
@@ -118,7 +92,7 @@ elseif(APPLE OR
        CMAKE_SYSTEM_NAME STREQUAL "NetBSD" OR
        CMAKE_SYSTEM_NAME STREQUAL "SunOS")
   set(HAVE_GETADDRINFO_THREADSAFE TRUE)
-elseif(CMAKE_SYSTEM_NAME MATCHES "BSD")
+elseif(BSD OR CMAKE_SYSTEM_NAME MATCHES "BSD")
   set(HAVE_GETADDRINFO_THREADSAFE FALSE)
 endif()
 
@@ -178,3 +152,5 @@ if(NOT WIN32 AND NOT DEFINED HAVE_CLOCK_GETTIME_MONOTONIC_RAW)
       return 0;
     }" HAVE_CLOCK_GETTIME_MONOTONIC_RAW)
 endif()
+
+unset(_source_epilogue)

+ 61 - 42
CMake/PickyWarnings.cmake

@@ -23,24 +23,27 @@
 ###########################################################################
 include(CheckCCompilerFlag)
 
-unset(WPICKY)
+unset(_picky)
 
 if(CURL_WERROR AND
    ((CMAKE_COMPILER_IS_GNUCC AND
      NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 5.0 AND
      NOT CMAKE_VERSION VERSION_LESS 3.23.0) OR  # to avoid check_symbol_exists() conflicting with GCC -pedantic-errors
    CMAKE_C_COMPILER_ID MATCHES "Clang"))
-  set(WPICKY "${WPICKY} -pedantic-errors")
+  list(APPEND _picky "-pedantic-errors")
+  if(MSVC)  # clang-cl
+    list(APPEND _picky "-Wno-language-extension-token")  # Override default error to make __int64 size detection pass
+  endif()
 endif()
 
 if(APPLE AND
    (CMAKE_C_COMPILER_ID STREQUAL "Clang"      AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.6) OR
    (CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 6.3))
-  set(WPICKY "${WPICKY} -Werror=partial-availability")  # clang 3.6  appleclang 6.3
+  list(APPEND _picky "-Werror=partial-availability")  # clang 3.6  appleclang 6.3
 endif()
 
 if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
-  set(WPICKY "${WPICKY} -Werror-implicit-function-declaration")  # clang 1.0  gcc 2.95
+  list(APPEND _picky "-Werror-implicit-function-declaration")  # clang 1.0  gcc 2.95
 endif()
 
 if(PICKY_COMPILER)
@@ -49,29 +52,29 @@ if(PICKY_COMPILER)
     # https://clang.llvm.org/docs/DiagnosticsReference.html
     # https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
 
-    # WPICKY_ENABLE = Options we want to enable as-is.
-    # WPICKY_DETECT = Options we want to test first and enable if available.
+    # _picky_enable = Options we want to enable as-is.
+    # _picky_detect = Options we want to test first and enable if available.
 
     # Prefer the -Wextra alias with clang.
     if(CMAKE_C_COMPILER_ID MATCHES "Clang")
-      set(WPICKY_ENABLE "-Wextra")
+      set(_picky_enable "-Wextra")
     else()
-      set(WPICKY_ENABLE "-W")
+      set(_picky_enable "-W")
     endif()
 
-    list(APPEND WPICKY_ENABLE
+    list(APPEND _picky_enable
       -Wall -pedantic
     )
 
     # ----------------------------------
     # Add new options here, if in doubt:
     # ----------------------------------
-    set(WPICKY_DETECT
+    set(_picky_detect
     )
 
     # Assume these options always exist with both clang and gcc.
     # Require clang 3.0 / gcc 2.95 or later.
-    list(APPEND WPICKY_ENABLE
+    list(APPEND _picky_enable
       -Wbad-function-cast                  # clang  2.7  gcc  2.95
       -Wconversion                         # clang  2.7  gcc  2.95
       -Winline                             # clang  1.0  gcc  1.0
@@ -89,7 +92,7 @@ if(PICKY_COMPILER)
     )
 
     # Always enable with clang, version dependent with gcc
-    set(WPICKY_COMMON_OLD
+    set(_picky_common_old
       -Waddress                            # clang  2.7  gcc  4.3
       -Wattributes                         # clang  2.7  gcc  4.1
       -Wcast-align                         # clang  1.0  gcc  4.2
@@ -118,7 +121,7 @@ if(PICKY_COMPILER)
       -Wvla                                # clang  2.8  gcc  4.3
     )
 
-    set(WPICKY_COMMON
+    set(_picky_common
       -Wdouble-promotion                   # clang  3.6  gcc  4.6  appleclang  6.3
       -Wenum-conversion                    # clang  3.2  gcc 10.0  appleclang  4.6  g++ 11.0
       -Wpragmas                            # clang  3.5  gcc  4.1  appleclang  6.0
@@ -126,51 +129,55 @@ if(PICKY_COMPILER)
     )
 
     if(CMAKE_C_COMPILER_ID MATCHES "Clang")
-      list(APPEND WPICKY_ENABLE
-        ${WPICKY_COMMON_OLD}
+      list(APPEND _picky_enable
+        ${_picky_common_old}
         -Wshift-sign-overflow              # clang  2.9
         -Wshorten-64-to-32                 # clang  1.0
-        -Wlanguage-extension-token         # clang  3.0
         -Wformat=2                         # clang  3.0  gcc  4.8
       )
+      if(NOT MSVC)
+        list(APPEND _picky_enable
+          -Wlanguage-extension-token         # clang  3.0  # Avoid for clang-cl to allow __int64
+        )
+      endif()
       # Enable based on compiler version
       if((CMAKE_C_COMPILER_ID STREQUAL "Clang"      AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.6) OR
          (CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 6.3))
-        list(APPEND WPICKY_ENABLE
-          ${WPICKY_COMMON}
-          -Wunreachable-code-break         # clang  3.5            appleclang  6.0
+        list(APPEND _picky_enable
+          ${_picky_common}
+        # -Wunreachable-code-break         # clang  3.5            appleclang  6.0  # Not used: Silent in "unity" builds
           -Wheader-guard                   # clang  3.4            appleclang  5.1
           -Wsometimes-uninitialized        # clang  3.2            appleclang  4.6
         )
       endif()
       if((CMAKE_C_COMPILER_ID STREQUAL "Clang"      AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.9) OR
          (CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 8.3))
-        list(APPEND WPICKY_ENABLE
+        list(APPEND _picky_enable
           -Wcomma                          # clang  3.9            appleclang  8.3
           -Wmissing-variable-declarations  # clang  3.2            appleclang  4.6
         )
       endif()
       if((CMAKE_C_COMPILER_ID STREQUAL "Clang"      AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 7.0) OR
          (CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 10.3))
-        list(APPEND WPICKY_ENABLE
+        list(APPEND _picky_enable
           -Wassign-enum                    # clang  7.0            appleclang 10.3
           -Wextra-semi-stmt                # clang  7.0            appleclang 10.3
         )
       endif()
       if((CMAKE_C_COMPILER_ID STREQUAL "Clang"      AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 10.0) OR
          (CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 12.4))
-        list(APPEND WPICKY_ENABLE
+        list(APPEND _picky_enable
           -Wimplicit-fallthrough           # clang  4.0  gcc  7.0  appleclang 12.4  # We do silencing for clang 10.0 and above only
         )
       endif()
     else()  # gcc
-      list(APPEND WPICKY_DETECT
-        ${WPICKY_COMMON}
+      list(APPEND _picky_detect
+        ${_picky_common}
       )
       # Enable based on compiler version
       if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.3)
-        list(APPEND WPICKY_ENABLE
-          ${WPICKY_COMMON_OLD}
+        list(APPEND _picky_enable
+          ${_picky_common_old}
           -Wclobbered                      #             gcc  4.3
           -Wmissing-parameter-type         #             gcc  4.3
           -Wold-style-declaration          #             gcc  4.3
@@ -179,22 +186,22 @@ if(PICKY_COMPILER)
         )
       endif()
       if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.5 AND MINGW)
-        list(APPEND WPICKY_ENABLE
+        list(APPEND _picky_enable
           -Wno-pedantic-ms-format          #             gcc  4.5 (MinGW-only)
         )
       endif()
       if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.8)
-        list(APPEND WPICKY_ENABLE
+        list(APPEND _picky_enable
           -Wformat=2                       # clang  3.0  gcc  4.8
         )
       endif()
       if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 5.0)
-        list(APPEND WPICKY_ENABLE
+        list(APPEND _picky_enable
           -Warray-bounds=2 -ftree-vrp      # clang  3.0  gcc  5.0 (clang default: -Warray-bounds)
         )
       endif()
       if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 6.0)
-        list(APPEND WPICKY_ENABLE
+        list(APPEND _picky_enable
           -Wduplicated-cond                #             gcc  6.0
           -Wnull-dereference               # clang  3.0  gcc  6.0 (clang default)
             -fdelete-null-pointer-checks
@@ -203,17 +210,16 @@ if(PICKY_COMPILER)
         )
       endif()
       if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 7.0)
-        list(APPEND WPICKY_ENABLE
+        list(APPEND _picky_enable
           -Walloc-zero                     #             gcc  7.0
           -Wduplicated-branches            #             gcc  7.0
-          -Wno-format-overflow             #             gcc  7.0
           -Wformat-truncation=2            #             gcc  7.0
           -Wimplicit-fallthrough           # clang  4.0  gcc  7.0
           -Wrestrict                       #             gcc  7.0
         )
       endif()
       if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 10.0)
-        list(APPEND WPICKY_ENABLE
+        list(APPEND _picky_enable
           -Warith-conversion               #             gcc 10.0
         )
       endif()
@@ -221,26 +227,39 @@ if(PICKY_COMPILER)
 
     #
 
-    foreach(_ccopt IN LISTS WPICKY_ENABLE)
-      set(WPICKY "${WPICKY} ${_ccopt}")
+    foreach(_ccopt IN LISTS _picky_enable)
+      list(APPEND _picky "${_ccopt}")
     endforeach()
 
-    foreach(_ccopt IN LISTS WPICKY_DETECT)
-      # surprisingly, CHECK_C_COMPILER_FLAG needs a new variable to store each new
-      # test result in.
+    foreach(_ccopt IN LISTS _picky_detect)
+      # Use a unique variable name 1. for meaningful log output 2. to have a fresh, undefined variable for each detection
       string(MAKE_C_IDENTIFIER "OPT${_ccopt}" _optvarname)
       # GCC only warns about unknown -Wno- options if there are also other diagnostic messages,
       # so test for the positive form instead
       string(REPLACE "-Wno-" "-W" _ccopt_on "${_ccopt}")
       check_c_compiler_flag(${_ccopt_on} ${_optvarname})
       if(${_optvarname})
-        set(WPICKY "${WPICKY} ${_ccopt}")
+        list(APPEND _picky "${_ccopt}")
       endif()
     endforeach()
   endif()
 endif()
 
-if(WPICKY)
-  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WPICKY}")
-  message(STATUS "Picky compiler options:${WPICKY}")
+# clang-cl
+if(CMAKE_C_COMPILER_ID STREQUAL "Clang" AND MSVC)
+  if(CMAKE_VERSION VERSION_LESS 3.12)
+    set(_picky_tmp "")
+    foreach(_ccopt IN LISTS _picky)
+      list(APPEND _picky_tmp "/clang:${_ccopt}")
+    endforeach()
+    set(_picky ${_picky_tmp})
+  else()
+    list(TRANSFORM _picky PREPEND "/clang:")
+  endif()
+endif()
+
+if(_picky)
+  string(REPLACE ";" " " _picky "${_picky}")
+  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_picky}")
+  message(STATUS "Picky compiler options: ${_picky}")
 endif()

+ 4 - 5
CMake/Platforms/WindowsCache.cmake

@@ -88,6 +88,7 @@ set(HAVE_FREEADDRINFO 1)
 set(HAVE_FCHMOD 0)
 set(HAVE_SOCKETPAIR 0)
 set(HAVE_SENDMSG 0)
+set(HAVE_SENDMMSG 0)
 set(HAVE_ALARM 0)
 set(HAVE_FCNTL 0)
 set(HAVE_GETPPID 0)
@@ -101,13 +102,12 @@ set(HAVE_IF_NAMETOINDEX 0)
 set(HAVE_GETRLIMIT 0)
 set(HAVE_SETRLIMIT 0)
 set(HAVE_FSETXATTR 0)
-set(HAVE_LIBSOCKET 0)
 set(HAVE_SETLOCALE 1)
 set(HAVE_SETMODE 1)
+set(HAVE__SETMODE 1)
 set(HAVE_GETPEERNAME 1)
 set(HAVE_GETSOCKNAME 1)
 set(HAVE_GETHOSTNAME 1)
-set(HAVE_LIBZ 0)
 
 set(HAVE_RECV 1)
 set(HAVE_SEND 1)
@@ -122,12 +122,13 @@ set(HAVE_IFADDRS_H 0)
 set(HAVE_IO_H 1)
 set(HAVE_NETDB_H 0)
 set(HAVE_NETINET_IN_H 0)
+set(HAVE_NETINET_IN6_H 0)
 set(HAVE_NETINET_TCP_H 0)
 set(HAVE_NETINET_UDP_H 0)
 set(HAVE_NET_IF_H 0)
 set(HAVE_IOCTL_SIOCGIFADDR 0)
 set(HAVE_POLL_H 0)
-set(HAVE_POLL_FINE 0)
+set(HAVE_POLL 0)
 set(HAVE_PWD_H 0)
 set(HAVE_SYS_EVENTFD_H 0)
 set(HAVE_SYS_FILIO_H 0)
@@ -147,7 +148,6 @@ set(HAVE_TERMIO_H 0)
 set(HAVE_LINUX_TCP_H 0)
 
 set(HAVE_FSEEKO 0)  # mingw-w64 2.0.0 and newer has it
-set(HAVE__FSEEKI64 1)
 set(HAVE_SOCKET 1)
 set(HAVE_SELECT 1)
 set(HAVE_STRDUP 1)
@@ -166,7 +166,6 @@ set(HAVE_GETHOSTBYNAME_R 0)
 set(HAVE_SIGNAL 1)
 set(HAVE_SIGACTION 0)
 set(HAVE_GLIBC_STRERROR_R 0)
-set(HAVE_MACH_ABSOLUTE_TIME 0)
 set(HAVE_GETIFADDRS 0)
 set(HAVE_FCNTL_O_NONBLOCK 0)
 set(HAVE_IOCTLSOCKET 1)

+ 9 - 10
CMake/curl-config.cmake.in

@@ -23,20 +23,19 @@
 ###########################################################################
 @PACKAGE_INIT@
 
-if(NOT DEFINED CURL_USE_PKGCONFIG)
-  if(UNIX OR (MSVC AND VCPKG_TOOLCHAIN))  # Keep in sync with root CMakeLists.txt
-    set(CURL_USE_PKGCONFIG ON)
-  else()
-    set(CURL_USE_PKGCONFIG OFF)
-  endif()
+if(UNIX OR VCPKG_TOOLCHAIN OR (MINGW AND NOT CMAKE_CROSSCOMPILING))  # Keep in sync with root CMakeLists.txt
+  set(_curl_use_pkgconfig_default ON)
+else()
+  set(_curl_use_pkgconfig_default OFF)
 endif()
+option(CURL_USE_PKGCONFIG "Enable pkg-config to detect @PROJECT_NAME@ dependencies" ${_curl_use_pkgconfig_default})
 
 include(CMakeFindDependencyMacro)
-if(@USE_OPENSSL@)
-  find_dependency(OpenSSL @OPENSSL_VERSION_MAJOR@)
+if("@USE_OPENSSL@")
+  find_dependency(OpenSSL "@OPENSSL_VERSION_MAJOR@")
 endif()
-if(@USE_ZLIB@)
-  find_dependency(ZLIB @ZLIB_VERSION_MAJOR@)
+if("@HAVE_LIBZ@")
+  find_dependency(ZLIB "@ZLIB_VERSION_MAJOR@")
 endif()
 
 include("${CMAKE_CURRENT_LIST_DIR}/@[email protected]")

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 323 - 236
CMakeLists.txt


+ 25 - 19
include/curl/curl.h

@@ -30,14 +30,15 @@
  */
 
 #ifdef CURL_NO_OLDIES
-#define CURL_STRICTER
+#define CURL_STRICTER /* not used since 8.11.0 */
 #endif
 
 /* Compile-time deprecation macros. */
-#if (defined(__GNUC__) &&                                               \
-  ((__GNUC__ > 12) || ((__GNUC__ == 12) && (__GNUC_MINOR__ >= 1 ))) ||  \
-  defined(__IAR_SYSTEMS_ICC__)) &&                                      \
-  !defined(__INTEL_COMPILER) &&                                         \
+#if (defined(__GNUC__) &&                                              \
+  ((__GNUC__ > 12) || ((__GNUC__ == 12) && (__GNUC_MINOR__ >= 1))) ||  \
+  (defined(__clang__) && __clang_major__ >= 3) ||                      \
+  defined(__IAR_SYSTEMS_ICC__)) &&                                     \
+  !defined(__INTEL_COMPILER) &&                                        \
   !defined(CURL_DISABLE_DEPRECATION) && !defined(BUILDING_LIBCURL)
 #define CURL_DEPRECATED(version, message)                       \
   __attribute__((deprecated("since " # version ". " message)))
@@ -113,13 +114,8 @@
 extern "C" {
 #endif
 
-#if defined(BUILDING_LIBCURL) || defined(CURL_STRICTER)
-typedef struct Curl_easy CURL;
-typedef struct Curl_share CURLSH;
-#else
 typedef void CURL;
 typedef void CURLSH;
-#endif
 
 /*
  * libcurl external API function linkage decorations.
@@ -253,12 +249,12 @@ typedef int (*curl_xferinfo_callback)(void *clientp,
 #endif
 
 #ifndef CURL_MAX_WRITE_SIZE
-  /* Tests have proven that 20K is a very bad buffer size for uploads on
-     Windows, while 16K for some odd reason performed a lot better.
-     We do the ifndef check to allow this value to easier be changed at build
-     time for those who feel adventurous. The practical minimum is about
-     400 bytes since libcurl uses a buffer of this size as a scratch area
-     (unrelated to network send operations). */
+  /* Tests have proven that 20K is a bad buffer size for uploads on Windows,
+     while 16K for some odd reason performed a lot better. We do the ifndef
+     check to allow this value to easier be changed at build time for those
+     who feel adventurous. The practical minimum is about 400 bytes since
+     libcurl uses a buffer of this size as a scratch area (unrelated to
+     network send operations). */
 #define CURL_MAX_WRITE_SIZE 16384
 #endif
 
@@ -555,14 +551,14 @@ typedef enum {
   CURLE_FTP_COULDNT_USE_REST,    /* 31 - the REST command failed */
   CURLE_OBSOLETE32,              /* 32 - NOT USED */
   CURLE_RANGE_ERROR,             /* 33 - RANGE "command" did not work */
-  CURLE_HTTP_POST_ERROR,         /* 34 */
+  CURLE_OBSOLETE34,              /* 34 */
   CURLE_SSL_CONNECT_ERROR,       /* 35 - wrong when connecting with SSL */
   CURLE_BAD_DOWNLOAD_RESUME,     /* 36 - could not resume download */
   CURLE_FILE_COULDNT_READ_FILE,  /* 37 */
   CURLE_LDAP_CANNOT_BIND,        /* 38 */
   CURLE_LDAP_SEARCH_FAILED,      /* 39 */
   CURLE_OBSOLETE40,              /* 40 - NOT USED */
-  CURLE_FUNCTION_NOT_FOUND,      /* 41 - NOT USED starting with 7.53.0 */
+  CURLE_OBSOLETE41,              /* 41 - NOT USED starting with 7.53.0 */
   CURLE_ABORTED_BY_CALLBACK,     /* 42 */
   CURLE_BAD_FUNCTION_ARGUMENT,   /* 43 */
   CURLE_OBSOLETE44,              /* 44 - NOT USED */
@@ -647,6 +643,12 @@ typedef enum {
 #ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
                           the obsolete stuff removed! */
 
+/* removed in 7.53.0 */
+#define CURLE_FUNCTION_NOT_FOUND CURLE_OBSOLETE41
+
+/* removed in 7.56.0 */
+#define CURLE_HTTP_POST_ERROR CURLE_OBSOLETE34
+
 /* Previously obsolete error code reused in 7.38.0 */
 #define CURLE_OBSOLETE16 CURLE_HTTP2
 
@@ -942,6 +944,9 @@ typedef enum {
    a client certificate for authentication. (Schannel) */
 #define CURLSSLOPT_AUTO_CLIENT_CERT (1<<5)
 
+/* If possible, send data using TLS 1.3 early data */
+#define CURLSSLOPT_EARLYDATA (1<<6)
+
 /* The default connection attempt delay in milliseconds for happy eyeballs.
    CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3 and happy-eyeballs-timeout-ms.d document
    this value, keep them in sync. */
@@ -2953,7 +2958,8 @@ typedef enum {
   CURLINFO_QUEUE_TIME_T     = CURLINFO_OFF_T + 65,
   CURLINFO_USED_PROXY       = CURLINFO_LONG + 66,
   CURLINFO_POSTTRANSFER_TIME_T = CURLINFO_OFF_T + 67,
-  CURLINFO_LASTONE          = 67
+  CURLINFO_EARLYDATA_SENT_T = CURLINFO_OFF_T + 68,
+  CURLINFO_LASTONE          = 68
 } CURLINFO;
 
 /* CURLINFO_RESPONSE_CODE is the new name for the option previously known as

+ 3 - 3
include/curl/curlver.h

@@ -32,12 +32,12 @@
 
 /* This is the version number of the libcurl package from which this header
    file origins: */
-#define LIBCURL_VERSION "8.10.1-DEV"
+#define LIBCURL_VERSION "8.11.1-DEV"
 
 /* The numeric version number is also available "in parts" by using these
    defines: */
 #define LIBCURL_VERSION_MAJOR 8
-#define LIBCURL_VERSION_MINOR 10
+#define LIBCURL_VERSION_MINOR 11
 #define LIBCURL_VERSION_PATCH 1
 
 /* This is the numeric version of the libcurl version number, meant for easier
@@ -59,7 +59,7 @@
    CURL_VERSION_BITS() macro since curl's own configure script greps for it
    and needs it to contain the full number.
 */
-#define LIBCURL_VERSION_NUM 0x080a01
+#define LIBCURL_VERSION_NUM 0x080b01
 
 /*
  * This is the date and time when the full source package was created. The

+ 7 - 11
include/curl/multi.h

@@ -54,11 +54,7 @@
 extern "C" {
 #endif
 
-#if defined(BUILDING_LIBCURL) || defined(CURL_STRICTER)
-typedef struct Curl_multi CURLM;
-#else
 typedef void CURLM;
-#endif
 
 typedef enum {
   CURLM_CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() or
@@ -248,13 +244,13 @@ CURL_EXTERN CURLMcode curl_multi_cleanup(CURLM *multi_handle);
  *          The data the returned pointer points to will not survive calling
  *          curl_multi_cleanup().
  *
- *          The 'CURLMsg' struct is meant to be very simple and only contain
- *          very basic information. If more involved information is wanted,
- *          we will provide the particular "transfer handle" in that struct
- *          and that should/could/would be used in subsequent
- *          curl_easy_getinfo() calls (or similar). The point being that we
- *          must never expose complex structs to applications, as then we will
- *          undoubtably get backwards compatibility problems in the future.
+ *          The 'CURLMsg' struct is meant to be simple and only contain basic
+ *          information. If more involved information is wanted, we will
+ *          provide the particular "transfer handle" in that struct and that
+ *          should/could/would be used in subsequent curl_easy_getinfo() calls
+ *          (or similar). The point being that we must never expose complex
+ *          structs to applications, as then we will undoubtably get backwards
+ *          compatibility problems in the future.
  *
  * Returns: A pointer to a filled-in struct, or NULL if it failed or ran out
  *          of structs. It also writes the number of messages left in the

+ 25 - 21
lib/CMakeLists.txt

@@ -21,8 +21,8 @@
 # SPDX-License-Identifier: curl
 #
 ###########################################################################
-set(LIB_NAME libcurl)
-set(LIBCURL_OUTPUT_NAME libcurl CACHE STRING "Basename of the curl library")
+set(LIB_NAME "libcurl")
+set(LIBCURL_OUTPUT_NAME "libcurl" CACHE STRING "Basename of the curl library")
 add_definitions("-DBUILDING_LIBCURL")
 
 configure_file("curl_config.h.cmake" "${CMAKE_CURRENT_BINARY_DIR}/curl_config.h")
@@ -39,14 +39,14 @@ list(APPEND HHEADERS "${CMAKE_CURRENT_BINARY_DIR}/curl_config.h")
 # The rest of the build
 
 include_directories(
-  "${CMAKE_CURRENT_BINARY_DIR}"
-  "${CMAKE_CURRENT_SOURCE_DIR}"
+  "${PROJECT_BINARY_DIR}/lib"  # for "curl_config.h"
+  "${PROJECT_SOURCE_DIR}/lib"  # for "curl_setup.h"
 )
 if(USE_ARES)
-  include_directories(${CARES_INCLUDE_DIRS})
+  include_directories(SYSTEM ${CARES_INCLUDE_DIRS})
 endif()
 
-if(BUILD_TESTING)
+if(CURL_BUILD_TESTING)
   add_library(
     curlu  # special libcurlu library just for unittests
     STATIC
@@ -112,7 +112,7 @@ if(SHARE_LIB_OBJECT)
 
   target_include_directories(${LIB_OBJECT} INTERFACE
     "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
-    "$<BUILD_INTERFACE:${CURL_SOURCE_DIR}/include>")
+    "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>")
 
   set(LIB_SOURCE $<TARGET_OBJECTS:${LIB_OBJECT}>)
 else()
@@ -125,7 +125,7 @@ if(BUILD_STATIC_LIBS)
   add_library(${LIB_STATIC} STATIC ${LIB_SOURCE})
   add_library(${PROJECT_NAME}::${LIB_STATIC} ALIAS ${LIB_STATIC})
   if(WIN32)
-    set_property(TARGET ${LIB_OBJECT} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_STATICLIB")
+    set_property(TARGET ${LIB_STATIC} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_STATICLIB")
   endif()
   target_link_libraries(${LIB_STATIC} PRIVATE ${CURL_LIBS})
   # Remove the "lib" prefix since the library is already named "libcurl".
@@ -145,7 +145,7 @@ if(BUILD_STATIC_LIBS)
 
   target_include_directories(${LIB_STATIC} INTERFACE
     "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
-    "$<BUILD_INTERFACE:${CURL_SOURCE_DIR}/include>")
+    "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>")
 endif()
 
 if(BUILD_SHARED_LIBS)
@@ -156,15 +156,14 @@ if(BUILD_SHARED_LIBS)
     if(CYGWIN)
       # For Cygwin always compile dllmain.c as a separate unit since it
       # includes windows.h, which should not be included in other units.
-      set_source_files_properties("dllmain.c" PROPERTIES
-        SKIP_UNITY_BUILD_INCLUSION ON)
+      set_source_files_properties("dllmain.c" PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON)
     endif()
     set_property(TARGET ${LIB_SHARED} APPEND PROPERTY SOURCES "dllmain.c")
   endif()
   if(WIN32)
     set_property(TARGET ${LIB_SHARED} APPEND PROPERTY SOURCES "libcurl.rc")
     if(CURL_HIDES_PRIVATE_SYMBOLS)
-      set_property(TARGET ${LIB_SHARED} APPEND PROPERTY SOURCES "${CURL_SOURCE_DIR}/lib/libcurl.def")
+      set_property(TARGET ${LIB_SHARED} APPEND PROPERTY SOURCES "${PROJECT_SOURCE_DIR}/lib/libcurl.def")
     endif()
   endif()
   target_link_libraries(${LIB_SHARED} PRIVATE ${CURL_LIBS})
@@ -185,7 +184,7 @@ if(BUILD_SHARED_LIBS)
 
   target_include_directories(${LIB_SHARED} INTERFACE
     "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
-    "$<BUILD_INTERFACE:${CURL_SOURCE_DIR}/include>")
+    "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>")
 
   if(CMAKE_DLL_NAME_WITH_SOVERSION OR
     CYGWIN OR
@@ -238,16 +237,21 @@ if(BUILD_SHARED_LIBS)
         set(CURL_LIBCURL_VERSIONED_SYMBOLS_PREFIX "WOLFSSL_")
       elseif(CURL_USE_GNUTLS)
         set(CURL_LIBCURL_VERSIONED_SYMBOLS_PREFIX "GNUTLS_")
+      elseif(CURL_USE_RUSTLS)
+        set(CURL_LIBCURL_VERSIONED_SYMBOLS_PREFIX "RUSTLS_")
       endif()
     endif()
-    file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/libcurl.vers" "
-      HIDDEN {};
-      CURL_${CURL_LIBCURL_VERSIONED_SYMBOLS_PREFIX}${_cmakesoname}
-      {
-        global: curl_*;
-        local: *;
-      };")
+    # Generate version script for the linker, for versioned symbols.
+    # Consumed variables:
+    #   CURL_LIBCURL_VERSIONED_SYMBOLS_PREFIX
+    #   CURL_LIBCURL_VERSIONED_SYMBOLS_SONAME
+    set(CURL_LIBCURL_VERSIONED_SYMBOLS_SONAME ${_cmakesoname})
+    configure_file(
+      "${CMAKE_CURRENT_SOURCE_DIR}/libcurl.vers.in"
+      "${CMAKE_CURRENT_BINARY_DIR}/libcurl.vers" @ONLY)
+    include(CMakePushCheckState)
     include(CheckCSourceCompiles)
+    cmake_push_check_state()
     set(CMAKE_REQUIRED_LINK_OPTIONS "-Wl,--version-script=${CMAKE_CURRENT_BINARY_DIR}/libcurl.vers")
     check_c_source_compiles("int main(void) { return 0; }" HAVE_VERSIONED_SYMBOLS)
     if(HAVE_VERSIONED_SYMBOLS)
@@ -256,7 +260,7 @@ if(BUILD_SHARED_LIBS)
     else()
       message(WARNING "Versioned symbols requested, but not supported by the toolchain.")
     endif()
-    unset(CMAKE_REQUIRED_LINK_OPTIONS)
+    cmake_pop_check_state()
   endif()
 endif()
 

+ 3 - 3
lib/Makefile.inc

@@ -97,9 +97,11 @@ LIB_VQUIC_HFILES = \
 LIB_VSSH_CFILES =  \
   vssh/libssh.c    \
   vssh/libssh2.c   \
+  vssh/curl_path.c \
   vssh/wolfssh.c
 
-LIB_VSSH_HFILES =  \
+LIB_VSSH_HFILES =    \
+  vssh/curl_path.h   \
   vssh/ssh.h
 
 LIB_CFILES =         \
@@ -131,7 +133,6 @@ LIB_CFILES =         \
   curl_memrchr.c     \
   curl_multibyte.c   \
   curl_ntlm_core.c   \
-  curl_path.c        \
   curl_range.c       \
   curl_rtmp.c        \
   curl_sasl.c        \
@@ -273,7 +274,6 @@ LIB_HFILES =         \
   curl_memrchr.h     \
   curl_multibyte.h   \
   curl_ntlm_core.h   \
-  curl_path.h        \
   curl_printf.h      \
   curl_range.h       \
   curl_rtmp.h        \

+ 16 - 18
lib/altsvc.c

@@ -64,6 +64,8 @@ static enum alpnid alpn2alpnid(char *name)
     return ALPN_h2;
   if(strcasecompare(name, H3VERSION))
     return ALPN_h3;
+  if(strcasecompare(name, "http/1.1"))
+    return ALPN_h1;
   return ALPN_none; /* unknown, probably rubbish input */
 }
 
@@ -92,6 +94,7 @@ static void altsvc_free(struct altsvc *as)
 
 static struct altsvc *altsvc_createid(const char *srchost,
                                       const char *dsthost,
+                                      size_t dlen, /* dsthost length */
                                       enum alpnid srcalpnid,
                                       enum alpnid dstalpnid,
                                       unsigned int srcport,
@@ -99,11 +102,9 @@ static struct altsvc *altsvc_createid(const char *srchost,
 {
   struct altsvc *as = calloc(1, sizeof(struct altsvc));
   size_t hlen;
-  size_t dlen;
   if(!as)
     return NULL;
   hlen = strlen(srchost);
-  dlen = strlen(dsthost);
   DEBUGASSERT(hlen);
   DEBUGASSERT(dlen);
   if(!hlen || !dlen) {
@@ -155,7 +156,8 @@ static struct altsvc *altsvc_create(char *srchost,
   enum alpnid srcalpnid = alpn2alpnid(srcalpn);
   if(!srcalpnid || !dstalpnid)
     return NULL;
-  return altsvc_createid(srchost, dsthost, srcalpnid, dstalpnid,
+  return altsvc_createid(srchost, dsthost, strlen(dsthost),
+                         srcalpnid, dstalpnid,
                          srcport, dstport);
 }
 
@@ -315,10 +317,8 @@ struct altsvcinfo *Curl_altsvc_init(void)
  */
 CURLcode Curl_altsvc_load(struct altsvcinfo *asi, const char *file)
 {
-  CURLcode result;
   DEBUGASSERT(asi);
-  result = altsvc_load(asi, file);
-  return result;
+  return altsvc_load(asi, file);
 }
 
 /*
@@ -490,8 +490,6 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
                            unsigned short srcport)
 {
   const char *p = value;
-  size_t len;
-  char namebuf[MAX_ALTSVC_HOSTLEN] = "";
   char alpnbuf[MAX_ALTSVC_ALPNLEN] = "";
   struct altsvc *as;
   unsigned short dstport = srcport; /* the same by default */
@@ -521,6 +519,7 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
       p++;
       if(*p == '\"') {
         const char *dsthost = "";
+        size_t dstlen = 0; /* destination hostname length */
         const char *value_ptr;
         char option[32];
         unsigned long num;
@@ -535,32 +534,31 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
           const char *hostp = p;
           if(*p == '[') {
             /* pass all valid IPv6 letters - does not handle zone id */
-            len = strspn(++p, "0123456789abcdefABCDEF:.");
-            if(p[len] != ']')
+            dstlen = strspn(++p, "0123456789abcdefABCDEF:.");
+            if(p[dstlen] != ']')
               /* invalid host syntax, bail out */
               break;
             /* we store the IPv6 numerical address *with* brackets */
-            len += 2;
-            p = &p[len-1];
+            dstlen += 2;
+            p = &p[dstlen-1];
           }
           else {
             while(*p && (ISALNUM(*p) || (*p == '.') || (*p == '-')))
               p++;
-            len = p - hostp;
+            dstlen = p - hostp;
           }
-          if(!len || (len >= MAX_ALTSVC_HOSTLEN)) {
+          if(!dstlen || (dstlen >= MAX_ALTSVC_HOSTLEN)) {
             infof(data, "Excessive alt-svc hostname, ignoring.");
             valid = FALSE;
           }
           else {
-            memcpy(namebuf, hostp, len);
-            namebuf[len] = 0;
-            dsthost = namebuf;
+            dsthost = hostp;
           }
         }
         else {
           /* no destination name, use source host */
           dsthost = srchost;
+          dstlen = strlen(srchost);
         }
         if(*p == ':') {
           unsigned long port = 0;
@@ -635,7 +633,7 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
                this is the first entry of the line. */
             altsvc_flush(asi, srcalpnid, srchost, srcport);
 
-          as = altsvc_createid(srchost, dsthost,
+          as = altsvc_createid(srchost, dsthost, dstlen,
                                srcalpnid, dstalpnid,
                                srcport, dstport);
           if(as) {

+ 9 - 18
lib/asyn-ares.c

@@ -290,23 +290,14 @@ static void destroy_async_data(struct Curl_async *async)
 int Curl_resolver_getsock(struct Curl_easy *data,
                           curl_socket_t *socks)
 {
-  struct timeval maxtime;
+  struct timeval maxtime = { CURL_TIMEOUT_RESOLVE, 0 };
   struct timeval timebuf;
-  struct timeval *timeout;
-  long milli;
   int max = ares_getsock((ares_channel)data->state.async.resolver,
                          (ares_socket_t *)socks, MAX_SOCKSPEREASYHANDLE);
-
-  maxtime.tv_sec = CURL_TIMEOUT_RESOLVE;
-  maxtime.tv_usec = 0;
-
-  timeout = ares_timeout((ares_channel)data->state.async.resolver, &maxtime,
-                         &timebuf);
-  milli = (long)curlx_tvtoms(timeout);
-  if(milli == 0)
-    milli += 10;
+  struct timeval *timeout =
+    ares_timeout((ares_channel)data->state.async.resolver, &maxtime, &timebuf);
+  timediff_t milli = curlx_tvtoms(timeout);
   Curl_expire(data, milli, EXPIRE_ASYNC_NAME);
-
   return max;
 }
 
@@ -366,10 +357,10 @@ static int waitperform(struct Curl_easy *data, timediff_t timeout_ms)
     /* move through the descriptors and ask for processing on them */
     for(i = 0; i < num; i++)
       ares_process_fd((ares_channel)data->state.async.resolver,
-                      (pfd[i].revents & (POLLRDNORM|POLLIN))?
-                      pfd[i].fd:ARES_SOCKET_BAD,
-                      (pfd[i].revents & (POLLWRNORM|POLLOUT))?
-                      pfd[i].fd:ARES_SOCKET_BAD);
+                      (pfd[i].revents & (POLLRDNORM|POLLIN)) ?
+                      pfd[i].fd : ARES_SOCKET_BAD,
+                      (pfd[i].revents & (POLLWRNORM|POLLOUT)) ?
+                      pfd[i].fd : ARES_SOCKET_BAD);
   }
   return nfds;
 }
@@ -801,7 +792,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
       }
 #endif /* CURLRES_IPV6 */
       hints.ai_family = pf;
-      hints.ai_socktype = (data->conn->transport == TRNSPRT_TCP)?
+      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

+ 4 - 4
lib/asyn-thread.c

@@ -286,7 +286,7 @@ static CURLcode getaddrinfo_complete(struct Curl_easy *data)
  * and wait on it.
  */
 static
-#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP)
+#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_UWP)
 DWORD
 #else
 unsigned int
@@ -311,7 +311,7 @@ CURL_STDCALL getaddrinfo_thread(void *arg)
   rc = Curl_getaddrinfo_ex(tsd->hostname, service, &tsd->hints, &tsd->res);
 
   if(rc) {
-    tsd->sock_error = SOCKERRNO?SOCKERRNO:rc;
+    tsd->sock_error = SOCKERRNO ? SOCKERRNO : rc;
     if(tsd->sock_error == 0)
       tsd->sock_error = RESOLVER_ENOMEM;
   }
@@ -354,7 +354,7 @@ CURL_STDCALL getaddrinfo_thread(void *arg)
  * gethostbyname_thread() resolves a name and then exits.
  */
 static
-#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP)
+#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_UWP)
 DWORD
 #else
 unsigned int
@@ -728,7 +728,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
 
   memset(&hints, 0, sizeof(hints));
   hints.ai_family = pf;
-  hints.ai_socktype = (data->conn->transport == TRNSPRT_TCP)?
+  hints.ai_socktype = (data->conn->transport == TRNSPRT_TCP) ?
     SOCK_STREAM : SOCK_DGRAM;
 
   reslv->start = Curl_now();

+ 4 - 4
lib/bufq.c

@@ -484,17 +484,17 @@ CURLcode Curl_bufq_cwrite(struct bufq *q,
   ssize_t n;
   CURLcode result;
   n = Curl_bufq_write(q, (const unsigned char *)buf, len, &result);
-  *pnwritten = (n < 0)? 0 : (size_t)n;
+  *pnwritten = (n < 0) ? 0 : (size_t)n;
   return result;
 }
 
 CURLcode Curl_bufq_unwrite(struct bufq *q, size_t len)
 {
   while(len && q->tail) {
-    len -= chunk_unwrite(q->head, len);
+    len -= chunk_unwrite(q->tail, len);
     prune_tail(q);
   }
-  return len? CURLE_AGAIN : CURLE_OK;
+  return len ? CURLE_AGAIN : CURLE_OK;
 }
 
 ssize_t Curl_bufq_read(struct bufq *q, unsigned char *buf, size_t len,
@@ -526,7 +526,7 @@ CURLcode Curl_bufq_cread(struct bufq *q, char *buf, size_t len,
   ssize_t n;
   CURLcode result;
   n = Curl_bufq_read(q, (unsigned char *)buf, len, &result);
-  *pnread = (n < 0)? 0 : (size_t)n;
+  *pnread = (n < 0) ? 0 : (size_t)n;
   return result;
 }
 

+ 4 - 4
lib/c-hyper.c

@@ -274,7 +274,7 @@ static CURLcode status_line(struct Curl_easy *data,
   /* We need to set 'httpcodeq' for functions that check the response code in
      a single place. */
   data->req.httpcode = http_status;
-  data->req.httpversion = http_version == HYPER_HTTP_VERSION_1_1? 11 :
+  data->req.httpversion = http_version == HYPER_HTTP_VERSION_1_1 ? 11 :
                           (http_version == HYPER_HTTP_VERSION_2 ? 20 : 10);
   if(data->state.hconnect)
     /* CONNECT */
@@ -481,8 +481,8 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
         goto out;
 
       k->deductheadercount =
-        (100 <= http_status && 199 >= http_status)?k->headerbytecount:0;
-#ifdef USE_WEBSOCKETS
+        (100 <= http_status && 199 >= http_status) ? k->headerbytecount : 0;
+#ifndef CURL_DISABLE_WEBSOCKETS
       if(k->upgr101 == UPGR101_WS) {
         if(http_status == 101) {
           /* verify the response */
@@ -1035,7 +1035,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
   }
 
   p_accept = Curl_checkheaders(data,
-                               STRCONST("Accept"))?NULL:"Accept: */*\r\n";
+                               STRCONST("Accept")) ? NULL : "Accept: */*\r\n";
   if(p_accept) {
     result = Curl_hyper_header(data, headers, p_accept);
     if(result)

+ 3 - 3
lib/cf-h1-proxy.c

@@ -299,7 +299,7 @@ static CURLcode on_resp_header(struct Curl_cfilter *cf,
      (checkprefix("Proxy-authenticate:", header) &&
       (407 == k->httpcode))) {
 
-    bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
+    bool proxy = (k->httpcode == 407);
     char *auth = Curl_copy_header_value(header);
     if(!auth)
       return CURLE_OUT_OF_MEMORY;
@@ -547,8 +547,8 @@ static CURLcode CONNECT_host(struct Curl_cfilter *cf,
   if(result)
     return result;
 
-  authority = aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"",
-                      port);
+  authority = aprintf("%s%s%s:%d", ipv6_ip ? "[":"", hostname,
+                      ipv6_ip ? "]" : "", port);
   if(!authority)
     return CURLE_OUT_OF_MEMORY;
 

+ 19 - 18
lib/cf-h2-proxy.c

@@ -98,7 +98,8 @@ static CURLcode tunnel_stream_init(struct Curl_cfilter *cf,
     return result;
 
   ts->authority = /* host:port with IPv6 support */
-    aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"", port);
+    aprintf("%s%s%s:%d", ipv6_ip ? "[":"", hostname,
+            ipv6_ip ? "]" : "", port);
   if(!ts->authority)
     return CURLE_OUT_OF_MEMORY;
 
@@ -276,6 +277,8 @@ static int proxy_h2_client_new(struct Curl_cfilter *cf,
 {
   struct cf_h2_proxy_ctx *ctx = cf->ctx;
   nghttp2_option *o;
+  nghttp2_mem mem = {NULL, Curl_nghttp2_malloc, Curl_nghttp2_free,
+                     Curl_nghttp2_calloc, Curl_nghttp2_realloc};
 
   int rc = nghttp2_option_new(&o);
   if(rc)
@@ -288,7 +291,7 @@ static int proxy_h2_client_new(struct Curl_cfilter *cf,
      HTTP field value. */
   nghttp2_option_set_no_rfc9113_leading_and_trailing_ws_validation(o, 1);
 #endif
-  rc = nghttp2_session_client_new2(&ctx->h2, cbs, cf, o);
+  rc = nghttp2_session_client_new3(&ctx->h2, cbs, cf, o, &mem);
   nghttp2_option_del(o);
   return rc;
 }
@@ -429,7 +432,7 @@ static CURLcode proxy_h2_nw_out_flush(struct Curl_cfilter *cf,
     return result;
   }
   CURL_TRC_CF(data, cf, "[0] nw send buffer flushed");
-  return Curl_bufq_is_empty(&ctx->outbufq)? CURLE_OK: CURLE_AGAIN;
+  return Curl_bufq_is_empty(&ctx->outbufq) ? CURLE_OK : CURLE_AGAIN;
 }
 
 /*
@@ -604,29 +607,27 @@ static int proxy_h2_fr_print(const nghttp2_frame *frame,
       return msnprintf(buffer, blen,
                        "FRAME[SETTINGS, len=%d]", (int)frame->hd.length);
     }
-    case NGHTTP2_PUSH_PROMISE: {
+    case NGHTTP2_PUSH_PROMISE:
       return msnprintf(buffer, blen,
                        "FRAME[PUSH_PROMISE, len=%d, hend=%d]",
                        (int)frame->hd.length,
                        !!(frame->hd.flags & NGHTTP2_FLAG_END_HEADERS));
-    }
-    case NGHTTP2_PING: {
+    case NGHTTP2_PING:
       return msnprintf(buffer, blen,
                        "FRAME[PING, len=%d, ack=%d]",
                        (int)frame->hd.length,
-                       frame->hd.flags&NGHTTP2_FLAG_ACK);
-    }
+                       frame->hd.flags & NGHTTP2_FLAG_ACK);
     case NGHTTP2_GOAWAY: {
       char scratch[128];
       size_t s_len = sizeof(scratch)/sizeof(scratch[0]);
-        size_t len = (frame->goaway.opaque_data_len < s_len)?
-                      frame->goaway.opaque_data_len : s_len-1;
-        if(len)
-          memcpy(scratch, frame->goaway.opaque_data, len);
-        scratch[len] = '\0';
-        return msnprintf(buffer, blen, "FRAME[GOAWAY, error=%d, reason='%s', "
-                         "last_stream=%d]", frame->goaway.error_code,
-                         scratch, frame->goaway.last_stream_id);
+      size_t len = (frame->goaway.opaque_data_len < s_len) ?
+        frame->goaway.opaque_data_len : s_len-1;
+      if(len)
+        memcpy(scratch, frame->goaway.opaque_data, len);
+      scratch[len] = '\0';
+      return msnprintf(buffer, blen, "FRAME[GOAWAY, error=%d, reason='%s', "
+                       "last_stream=%d]", frame->goaway.error_code,
+                       scratch, frame->goaway.last_stream_id);
     }
     case NGHTTP2_WINDOW_UPDATE: {
       return msnprintf(buffer, blen,
@@ -1220,7 +1221,7 @@ static bool cf_h2_proxy_data_pending(struct Curl_cfilter *cf,
      (ctx && ctx->tunnel.state == H2_TUNNEL_ESTABLISHED &&
       !Curl_bufq_is_empty(&ctx->tunnel.recvbuf)))
     return TRUE;
-  return cf->next? cf->next->cft->has_data_pending(cf->next, data) : FALSE;
+  return cf->next ? cf->next->cft->has_data_pending(cf->next, data) : FALSE;
 }
 
 static void cf_h2_proxy_adjust_pollset(struct Curl_cfilter *cf,
@@ -1586,7 +1587,7 @@ static CURLcode cf_h2_proxy_query(struct Curl_cfilter *cf,
   default:
     break;
   }
-  return cf->next?
+  return cf->next ?
     cf->next->cft->query(cf->next, data, query, pres1, pres2) :
     CURLE_UNKNOWN_OPTION;
 }

+ 2 - 2
lib/cf-haproxy.c

@@ -93,7 +93,7 @@ static CURLcode cf_haproxy_date_out_set(struct Curl_cfilter*cf,
     client_ip = ipquad.local_ip;
 
   result = Curl_dyn_addf(&ctx->data_out, "PROXY %s %s %s %i %i\r\n",
-                         is_ipv6? "TCP6" : "TCP4",
+                         is_ipv6 ? "TCP6" : "TCP4",
                          client_ip, ipquad.remote_ip,
                          ipquad.local_port, ipquad.remote_port);
 
@@ -231,7 +231,7 @@ static CURLcode cf_haproxy_create(struct Curl_cfilter **pcf,
 
 out:
   cf_haproxy_ctx_free(ctx);
-  *pcf = result? NULL : cf;
+  *pcf = result ? NULL : cf;
   return result;
 }
 

+ 17 - 10
lib/cf-https-connect.c

@@ -174,6 +174,7 @@ static CURLcode baller_connected(struct Curl_cfilter *cf,
 {
   struct cf_hc_ctx *ctx = cf->ctx;
   CURLcode result = CURLE_OK;
+  int reply_ms;
 
   DEBUGASSERT(winner->cf);
   if(winner != &ctx->h3_baller)
@@ -181,9 +182,15 @@ static CURLcode baller_connected(struct Curl_cfilter *cf,
   if(winner != &ctx->h21_baller)
     cf_hc_baller_reset(&ctx->h21_baller, data);
 
-  CURL_TRC_CF(data, cf, "connect+handshake %s: %dms, 1st data: %dms",
-              winner->name, (int)Curl_timediff(Curl_now(), winner->started),
-              cf_hc_baller_reply_ms(winner, data));
+  reply_ms = cf_hc_baller_reply_ms(winner, data);
+  if(reply_ms >= 0)
+    CURL_TRC_CF(data, cf, "connect+handshake %s: %dms, 1st data: %dms",
+                winner->name, (int)Curl_timediff(Curl_now(), winner->started),
+                reply_ms);
+  else
+    CURL_TRC_CF(data, cf, "deferred handshake %s: %dms",
+                winner->name, (int)Curl_timediff(Curl_now(), winner->started));
+
   cf->next = winner->cf;
   winner->cf = NULL;
 
@@ -275,7 +282,7 @@ static CURLcode cf_hc_connect(struct Curl_cfilter *cf,
     }
     else if(ctx->h21_baller.enabled)
       cf_hc_baller_init(&ctx->h21_baller, cf, data, "h21",
-                       cf->conn->transport);
+                        cf->conn->transport);
     ctx->state = CF_HC_CONNECT;
     FALLTHROUGH();
 
@@ -306,8 +313,8 @@ static CURLcode cf_hc_connect(struct Curl_cfilter *cf,
        (!ctx->h21_baller.enabled || ctx->h21_baller.result)) {
       /* both failed or disabled. we give up */
       CURL_TRC_CF(data, cf, "connect, all failed");
-      result = ctx->result = ctx->h3_baller.enabled?
-                              ctx->h3_baller.result : ctx->h21_baller.result;
+      result = ctx->result = ctx->h3_baller.enabled ?
+        ctx->h3_baller.result : ctx->h21_baller.result;
       ctx->state = CF_HC_FAILURE;
       goto out;
     }
@@ -420,13 +427,13 @@ static struct curltime cf_get_max_baller_time(struct Curl_cfilter *cf,
 
   memset(&tmax, 0, sizeof(tmax));
   memset(&t, 0, sizeof(t));
-  cfb = ctx->h21_baller.enabled? ctx->h21_baller.cf : NULL;
+  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;
+  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;
@@ -464,7 +471,7 @@ static CURLcode cf_hc_query(struct Curl_cfilter *cf,
       break;
     }
   }
-  return cf->next?
+  return cf->next ?
     cf->next->cft->query(cf->next, data, query, pres1, pres2) :
     CURLE_UNKNOWN_OPTION;
 }
@@ -553,7 +560,7 @@ static CURLcode cf_hc_create(struct Curl_cfilter **pcf,
   cf_hc_reset(cf, data);
 
 out:
-  *pcf = result? NULL : cf;
+  *pcf = result ? NULL : cf;
   free(ctx);
   return result;
 }

+ 214 - 116
lib/cf-socket.c

@@ -177,7 +177,7 @@ static void
 tcpkeepalive(struct Curl_easy *data,
              curl_socket_t sockfd)
 {
-  int optval = data->set.tcp_keepalive?1:0;
+  int optval = data->set.tcp_keepalive ? 1 : 0;
 
   /* only set IDLE and INTVL if setting KEEPALIVE is successful */
   if(setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE,
@@ -336,7 +336,7 @@ void Curl_sock_assign_addr(struct Curl_sockaddr_ex *dest,
 
   if(dest->addrlen > sizeof(struct Curl_sockaddr_storage))
     dest->addrlen = sizeof(struct Curl_sockaddr_storage);
-  memcpy(&dest->sa_addr, ai->ai_addr, dest->addrlen);
+  memcpy(&dest->curl_sa_addr, ai->ai_addr, dest->addrlen);
 }
 
 static CURLcode socket_open(struct Curl_easy *data,
@@ -355,11 +355,11 @@ static CURLcode socket_open(struct Curl_easy *data,
     * might have been changed and this 'new' address will actually be used
     * here to connect.
     */
-    Curl_set_in_callback(data, true);
+    Curl_set_in_callback(data, TRUE);
     *sockfd = data->set.fopensocket(data->set.opensocket_client,
                                     CURLSOCKTYPE_IPCXN,
                                     (struct curl_sockaddr *)addr);
-    Curl_set_in_callback(data, false);
+    Curl_set_in_callback(data, FALSE);
   }
   else {
     /* opensocket callback not set, so simply create the socket now */
@@ -372,7 +372,7 @@ static CURLcode socket_open(struct Curl_easy *data,
 
 #if defined(USE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
   if(data->conn->scope_id && (addr->family == AF_INET6)) {
-    struct sockaddr_in6 * const sa6 = (void *)&addr->sa_addr;
+    struct sockaddr_in6 * const sa6 = (void *)&addr->curl_sa_addr;
     sa6->sin6_scope_id = data->conn->scope_id;
   }
 #endif
@@ -413,9 +413,9 @@ static int socket_close(struct Curl_easy *data, struct connectdata *conn,
   if(use_callback && conn && conn->fclosesocket) {
     int rc;
     Curl_multi_closed(data, sock);
-    Curl_set_in_callback(data, true);
+    Curl_set_in_callback(data, TRUE);
     rc = conn->fclosesocket(conn->closesocket_client, sock);
-    Curl_set_in_callback(data, false);
+    Curl_set_in_callback(data, FALSE);
     return rc;
   }
 
@@ -600,36 +600,39 @@ static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn,
   if(!iface && !host && !port)
     /* no local kind of binding was requested */
     return CURLE_OK;
+  else if(iface && (strlen(iface) >= 255) )
+    return CURLE_BAD_FUNCTION_ARGUMENT;
 
   memset(&sa, 0, sizeof(struct Curl_sockaddr_storage));
 
-  if(iface && (strlen(iface)<255) ) {
+  if(iface || host) {
     char myhost[256] = "";
     int done = 0; /* -1 for error, 1 for address found */
     if2ip_result_t if2ip_result = IF2IP_NOT_FOUND;
 
-    /* interface */
 #ifdef SO_BINDTODEVICE
-    /*
-      * This binds the local socket to a particular interface. This will
-      * force even requests to other local interfaces to go out the external
-      * interface. Only bind to the interface when specified as interface,
-      * not just as a hostname or ip address.
-      *
-      * The interface might be a VRF, eg: vrf-blue, which means it cannot be
-      * converted to an IP address and would fail Curl_if2ip. Simply try to
-      * use it straight away.
-      */
-    if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
-                  iface, (curl_socklen_t)strlen(iface) + 1) == 0) {
-      /* This is often "errno 1, error: Operation not permitted" if you are
-        * not running as root or another suitable privileged user. If it
-        * succeeds it means the parameter was a valid interface and not an IP
-        * address. Return immediately.
-        */
-      if(!host_input) {
-        infof(data, "socket successfully bound to interface '%s'", iface);
-        return CURLE_OK;
+    if(iface) {
+      /*
+       * This binds the local socket to a particular interface. This will
+       * force even requests to other local interfaces to go out the external
+       * interface. Only bind to the interface when specified as interface,
+       * not just as a hostname or ip address.
+       *
+       * The interface might be a VRF, eg: vrf-blue, which means it cannot be
+       * converted to an IP address and would fail Curl_if2ip. Simply try to
+       * use it straight away.
+       */
+      if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
+                    iface, (curl_socklen_t)strlen(iface) + 1) == 0) {
+        /* This is often "errno 1, error: Operation not permitted" if you are
+         * not running as root or another suitable privileged user. If it
+         * succeeds it means the parameter was a valid interface and not an IP
+         * address. Return immediately.
+         */
+        if(!host_input) {
+          infof(data, "socket successfully bound to interface '%s'", iface);
+          return CURLE_OK;
+        }
       }
     }
 #endif
@@ -1088,13 +1091,14 @@ static CURLcode set_remote_ip(struct Curl_cfilter *cf,
   struct cf_socket_ctx *ctx = cf->ctx;
 
   /* store remote address and port used in this connection attempt */
-  if(!Curl_addr2string(&ctx->addr.sa_addr, (curl_socklen_t)ctx->addr.addrlen,
+  if(!Curl_addr2string(&ctx->addr.curl_sa_addr,
+                       (curl_socklen_t)ctx->addr.addrlen,
                        ctx->ip.remote_ip, &ctx->ip.remote_port)) {
     char buffer[STRERROR_LEN];
 
     ctx->error = errno;
     /* malformed address or bug in inet_ntop, try next address */
-    failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
+    failf(data, "curl_sa_addr inet_ntop() failed with errno %d: %s",
           errno, Curl_strerror(errno, buffer, sizeof(buffer)));
     return CURLE_FAILED_INIT;
   }
@@ -1163,11 +1167,11 @@ static CURLcode cf_socket_open(struct Curl_cfilter *cf,
 
   if(data->set.fsockopt) {
     /* activate callback for setting socket options */
-    Curl_set_in_callback(data, true);
+    Curl_set_in_callback(data, TRUE);
     error = data->set.fsockopt(data->set.sockopt_client,
                                ctx->sock,
                                CURLSOCKTYPE_IPCXN);
-    Curl_set_in_callback(data, false);
+    Curl_set_in_callback(data, FALSE);
 
     if(error == CURL_SOCKOPT_ALREADY_CONNECTED)
       isconnected = TRUE;
@@ -1185,7 +1189,7 @@ static CURLcode cf_socket_open(struct Curl_cfilter *cf,
 #endif
     ) {
     result = bindlocal(data, cf->conn, ctx->sock, ctx->addr.family,
-                       Curl_ipv6_scope(&ctx->addr.sa_addr));
+                       Curl_ipv6_scope(&ctx->addr.curl_sa_addr));
     if(result) {
       if(result == CURLE_UNSUPPORTED_PROTOCOL) {
         /* The address family is not supported on this interface.
@@ -1257,7 +1261,7 @@ static int do_connect(struct Curl_cfilter *cf, struct Curl_easy *data,
       endpoints.sae_srcif = 0;
       endpoints.sae_srcaddr = NULL;
       endpoints.sae_srcaddrlen = 0;
-      endpoints.sae_dstaddr = &ctx->addr.sa_addr;
+      endpoints.sae_dstaddr = &ctx->addr.curl_sa_addr;
       endpoints.sae_dstaddrlen = ctx->addr.addrlen;
 
       rc = connectx(ctx->sock, &endpoints, SAE_ASSOCID_ANY,
@@ -1265,10 +1269,10 @@ static int do_connect(struct Curl_cfilter *cf, struct Curl_easy *data,
                     NULL, 0, NULL, NULL);
     }
     else {
-      rc = connect(ctx->sock, &ctx->addr.sa_addr, ctx->addr.addrlen);
+      rc = connect(ctx->sock, &ctx->addr.curl_sa_addr, ctx->addr.addrlen);
     }
 #  else
-    rc = connect(ctx->sock, &ctx->addr.sa_addr, ctx->addr.addrlen);
+    rc = connect(ctx->sock, &ctx->addr.curl_sa_addr, ctx->addr.addrlen);
 #  endif /* HAVE_BUILTIN_AVAILABLE */
 #elif defined(TCP_FASTOPEN_CONNECT) /* Linux >= 4.11 */
     if(setsockopt(ctx->sock, IPPROTO_TCP, TCP_FASTOPEN_CONNECT,
@@ -1276,16 +1280,16 @@ static int do_connect(struct Curl_cfilter *cf, struct Curl_easy *data,
       infof(data, "Failed to enable TCP Fast Open on fd %" FMT_SOCKET_T,
             ctx->sock);
 
-    rc = connect(ctx->sock, &ctx->addr.sa_addr, ctx->addr.addrlen);
+    rc = connect(ctx->sock, &ctx->addr.curl_sa_addr, ctx->addr.addrlen);
 #elif defined(MSG_FASTOPEN) /* old Linux */
     if(cf->conn->given->flags & PROTOPT_SSL)
-      rc = connect(ctx->sock, &ctx->addr.sa_addr, ctx->addr.addrlen);
+      rc = connect(ctx->sock, &ctx->addr.curl_sa_addr, ctx->addr.addrlen);
     else
       rc = 0; /* Do nothing */
 #endif
   }
   else {
-    rc = connect(ctx->sock, &ctx->addr.sa_addr,
+    rc = connect(ctx->sock, &ctx->addr.curl_sa_addr,
                  (curl_socklen_t)ctx->addr.addrlen);
   }
   return rc;
@@ -1309,7 +1313,7 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf,
   if(blocking)
     return CURLE_UNSUPPORTED_PROTOCOL;
 
-  *done = FALSE; /* a very negative world view is best */
+  *done = FALSE; /* a negative world view is best */
   if(ctx->sock == CURL_SOCKET_BAD) {
     int error;
 
@@ -1507,7 +1511,7 @@ static ssize_t cf_socket_send(struct Curl_cfilter *cf, struct Curl_easy *data,
 #if defined(MSG_FASTOPEN) && !defined(TCP_FASTOPEN_CONNECT) /* Linux */
   if(cf->conn->bits.tcp_fastopen) {
     nwritten = sendto(ctx->sock, buf, len, MSG_FASTOPEN,
-                      &cf->conn->remote_addr->sa_addr,
+                      &cf->conn->remote_addr->curl_sa_addr,
                       cf->conn->remote_addr->addrlen);
     cf->conn->bits.tcp_fastopen = FALSE;
   }
@@ -1642,7 +1646,7 @@ static void cf_socket_active(struct Curl_cfilter *cf, struct Curl_easy *data)
     cf->conn->primary = ctx->ip;
     cf->conn->remote_addr = &ctx->addr;
   #ifdef USE_IPV6
-    cf->conn->bits.ipv6 = (ctx->addr.family == AF_INET6)? TRUE : FALSE;
+    cf->conn->bits.ipv6 = (ctx->addr.family == AF_INET6);
   #endif
   }
   else {
@@ -1725,7 +1729,7 @@ static CURLcode cf_socket_query(struct Curl_cfilter *cf,
   case CF_QUERY_CONNECT_REPLY_MS:
     if(ctx->got_first_byte) {
       timediff_t ms = Curl_timediff(ctx->first_byte_at, ctx->started_at);
-      *pres1 = (ms < INT_MAX)? (int)ms : INT_MAX;
+      *pres1 = (ms < INT_MAX) ? (int)ms : INT_MAX;
     }
     else
       *pres1 = -1;
@@ -1750,7 +1754,7 @@ static CURLcode cf_socket_query(struct Curl_cfilter *cf,
   }
   case CF_QUERY_IP_INFO:
 #ifdef USE_IPV6
-    *pres1 = (ctx->addr.family == AF_INET6)? TRUE : FALSE;
+    *pres1 = (ctx->addr.family == AF_INET6);
 #else
     *pres1 = FALSE;
 #endif
@@ -1759,7 +1763,7 @@ static CURLcode cf_socket_query(struct Curl_cfilter *cf,
   default:
     break;
   }
-  return cf->next?
+  return cf->next ?
     cf->next->cft->query(cf->next, data, query, pres1, pres2) :
     CURLE_UNKNOWN_OPTION;
 }
@@ -1806,7 +1810,7 @@ CURLcode Curl_cf_tcp_create(struct Curl_cfilter **pcf,
   result = Curl_cf_create(&cf, &Curl_cft_tcp, ctx);
 
 out:
-  *pcf = (!result)? cf : NULL;
+  *pcf = (!result) ? cf : NULL;
   if(result) {
     Curl_safefree(cf);
     Curl_safefree(ctx);
@@ -1827,7 +1831,7 @@ static CURLcode cf_udp_setup_quic(struct Curl_cfilter *cf,
   /* QUIC needs a connected socket, nonblocking */
   DEBUGASSERT(ctx->sock != CURL_SOCKET_BAD);
 
-  rc = connect(ctx->sock, &ctx->addr.sa_addr,
+  rc = connect(ctx->sock, &ctx->addr.curl_sa_addr,
                (curl_socklen_t)ctx->addr.addrlen);
   if(-1 == rc) {
     return socket_connect_result(data, ctx->ip.remote_ip, SOCKERRNO);
@@ -1836,7 +1840,7 @@ static CURLcode cf_udp_setup_quic(struct Curl_cfilter *cf,
   set_local_ip(cf, data);
   CURL_TRC_CF(data, cf, "%s socket %" FMT_SOCKET_T
               " connected: [%s:%d] -> [%s:%d]",
-              (ctx->transport == TRNSPRT_QUIC)? "QUIC" : "UDP",
+              (ctx->transport == TRNSPRT_QUIC) ? "QUIC" : "UDP",
               ctx->sock, ctx->ip.local_ip, ctx->ip.local_port,
               ctx->ip.remote_ip, ctx->ip.remote_port);
 
@@ -1955,7 +1959,7 @@ CURLcode Curl_cf_udp_create(struct Curl_cfilter **pcf,
   result = Curl_cf_create(&cf, &Curl_cft_udp, ctx);
 
 out:
-  *pcf = (!result)? cf : NULL;
+  *pcf = (!result) ? cf : NULL;
   if(result) {
     Curl_safefree(cf);
     Curl_safefree(ctx);
@@ -2007,7 +2011,7 @@ CURLcode Curl_cf_unix_create(struct Curl_cfilter **pcf,
   result = Curl_cf_create(&cf, &Curl_cft_unix, ctx);
 
 out:
-  *pcf = (!result)? cf : NULL;
+  *pcf = (!result) ? cf : NULL;
   if(result) {
     Curl_safefree(cf);
     Curl_safefree(ctx);
@@ -2016,10 +2020,84 @@ out:
   return result;
 }
 
+static timediff_t cf_tcp_accept_timeleft(struct Curl_cfilter *cf,
+                                          struct Curl_easy *data)
+{
+  struct cf_socket_ctx *ctx = cf->ctx;
+  timediff_t timeout_ms = DEFAULT_ACCEPT_TIMEOUT;
+  timediff_t other;
+  struct curltime now;
+
+#ifndef CURL_DISABLE_FTP
+  if(data->set.accepttimeout > 0)
+    timeout_ms = data->set.accepttimeout;
+#endif
+
+  now = Curl_now();
+  /* check if the generic timeout possibly is set shorter */
+  other = Curl_timeleft(data, &now, FALSE);
+  if(other && (other < timeout_ms))
+    /* note that this also works fine for when other happens to be negative
+       due to it already having elapsed */
+    timeout_ms = other;
+  else {
+    /* subtract elapsed time */
+    timeout_ms -= Curl_timediff(now, ctx->started_at);
+    if(!timeout_ms)
+      /* avoid returning 0 as that means no timeout! */
+      timeout_ms = -1;
+  }
+  return timeout_ms;
+}
+
+static void cf_tcp_set_accepted_remote_ip(struct Curl_cfilter *cf,
+                                          struct Curl_easy *data)
+{
+  struct cf_socket_ctx *ctx = cf->ctx;
+#ifdef HAVE_GETPEERNAME
+  char buffer[STRERROR_LEN];
+  struct Curl_sockaddr_storage ssrem;
+  curl_socklen_t plen;
+
+  ctx->ip.remote_ip[0] = 0;
+  ctx->ip.remote_port = 0;
+  plen = sizeof(ssrem);
+  memset(&ssrem, 0, plen);
+  if(getpeername(ctx->sock, (struct sockaddr*) &ssrem, &plen)) {
+    int error = SOCKERRNO;
+    failf(data, "getpeername() failed with errno %d: %s",
+          error, Curl_strerror(error, buffer, sizeof(buffer)));
+    return;
+  }
+  if(!Curl_addr2string((struct sockaddr*)&ssrem, plen,
+                       ctx->ip.remote_ip, &ctx->ip.remote_port)) {
+    failf(data, "ssrem inet_ntop() failed with errno %d: %s",
+          errno, Curl_strerror(errno, buffer, sizeof(buffer)));
+    return;
+  }
+#else
+  ctx->ip.remote_ip[0] = 0;
+  ctx->ip.remote_port = 0;
+  (void)data;
+#endif
+}
+
 static CURLcode cf_tcp_accept_connect(struct Curl_cfilter *cf,
                                       struct Curl_easy *data,
                                       bool blocking, bool *done)
 {
+  struct cf_socket_ctx *ctx = cf->ctx;
+#ifdef USE_IPV6
+  struct Curl_sockaddr_storage add;
+#else
+  struct sockaddr_in add;
+#endif
+  curl_socklen_t size = (curl_socklen_t) sizeof(add);
+  curl_socket_t s_accepted = CURL_SOCKET_BAD;
+  timediff_t timeout_ms;
+  int socketstate = 0;
+  bool incoming = FALSE;
+
   /* we start accepted, if we ever close, we cannot go on */
   (void)data;
   (void)blocking;
@@ -2027,7 +2105,79 @@ static CURLcode cf_tcp_accept_connect(struct Curl_cfilter *cf,
     *done = TRUE;
     return CURLE_OK;
   }
-  return CURLE_FAILED_INIT;
+
+  timeout_ms = cf_tcp_accept_timeleft(cf, data);
+  if(timeout_ms < 0) {
+    /* if a timeout was already reached, bail out */
+    failf(data, "Accept timeout occurred while waiting server connect");
+    return CURLE_FTP_ACCEPT_TIMEOUT;
+  }
+
+  CURL_TRC_CF(data, cf, "Checking for incoming on fd=%" FMT_SOCKET_T
+              " ip=%s:%d", ctx->sock, ctx->ip.local_ip, ctx->ip.local_port);
+  socketstate = Curl_socket_check(ctx->sock, CURL_SOCKET_BAD,
+                                  CURL_SOCKET_BAD, 0);
+  CURL_TRC_CF(data, cf, "socket_check -> %x", socketstate);
+  switch(socketstate) {
+  case -1: /* error */
+    /* let's die here */
+    failf(data, "Error while waiting for server connect");
+    return CURLE_FTP_ACCEPT_FAILED;
+  default:
+    if(socketstate & CURL_CSELECT_IN) {
+      infof(data, "Ready to accept data connection from server");
+      incoming = TRUE;
+    }
+    break;
+  }
+
+  if(!incoming) {
+    CURL_TRC_CF(data, cf, "nothing heard from the server yet");
+    *done = FALSE;
+    return CURLE_OK;
+  }
+
+  if(0 == getsockname(ctx->sock, (struct sockaddr *) &add, &size)) {
+    size = sizeof(add);
+    s_accepted = accept(ctx->sock, (struct sockaddr *) &add, &size);
+  }
+
+  if(CURL_SOCKET_BAD == s_accepted) {
+    failf(data, "Error accept()ing server connect");
+    return CURLE_FTP_PORT_FAILED;
+  }
+
+  infof(data, "Connection accepted from server");
+  (void)curlx_nonblock(s_accepted, TRUE); /* enable non-blocking */
+  /* Replace any filter on SECONDARY with one listening on this socket */
+  ctx->listening = FALSE;
+  ctx->accepted = TRUE;
+  socket_close(data, cf->conn, TRUE, ctx->sock);
+  ctx->sock = s_accepted;
+
+  cf->conn->sock[cf->sockindex] = ctx->sock;
+  cf_tcp_set_accepted_remote_ip(cf, data);
+  set_local_ip(cf, data);
+  ctx->active = TRUE;
+  ctx->connected_at = Curl_now();
+  cf->connected = TRUE;
+  CURL_TRC_CF(data, cf, "accepted_set(sock=%" FMT_SOCKET_T
+              ", remote=%s port=%d)",
+              ctx->sock, ctx->ip.remote_ip, ctx->ip.remote_port);
+
+  if(data->set.fsockopt) {
+    int error = 0;
+
+    /* activate callback for setting socket options */
+    Curl_set_in_callback(data, true);
+    error = data->set.fsockopt(data->set.sockopt_client,
+                               ctx->sock, CURLSOCKTYPE_ACCEPT);
+    Curl_set_in_callback(data, false);
+
+    if(error)
+      return CURLE_ABORTED_BY_CALLBACK;
+  }
+  return CURLE_OK;
 }
 
 struct Curl_cftype Curl_cft_tcp_accept = {
@@ -2075,13 +2225,12 @@ CURLcode Curl_conn_tcp_listen_set(struct Curl_easy *data,
     goto out;
   Curl_conn_cf_add(data, conn, sockindex, cf);
 
+  ctx->started_at = Curl_now();
   conn->sock[sockindex] = ctx->sock;
   set_local_ip(cf, data);
-  ctx->active = TRUE;
-  ctx->connected_at = Curl_now();
-  cf->connected = TRUE;
-  CURL_TRC_CF(data, cf, "Curl_conn_tcp_listen_set(%" FMT_SOCKET_T ")",
-              ctx->sock);
+  CURL_TRC_CF(data, cf, "set filter for listen socket fd=%" FMT_SOCKET_T
+              " ip=%s:%d", ctx->sock,
+              ctx->ip.local_ip, ctx->ip.local_port);
 
 out:
   if(result) {
@@ -2091,67 +2240,16 @@ out:
   return result;
 }
 
-static void set_accepted_remote_ip(struct Curl_cfilter *cf,
-                                   struct Curl_easy *data)
+bool Curl_conn_is_tcp_listen(struct Curl_easy *data,
+                             int sockindex)
 {
-  struct cf_socket_ctx *ctx = cf->ctx;
-#ifdef HAVE_GETPEERNAME
-  char buffer[STRERROR_LEN];
-  struct Curl_sockaddr_storage ssrem;
-  curl_socklen_t plen;
-
-  ctx->ip.remote_ip[0] = 0;
-  ctx->ip.remote_port = 0;
-  plen = sizeof(ssrem);
-  memset(&ssrem, 0, plen);
-  if(getpeername(ctx->sock, (struct sockaddr*) &ssrem, &plen)) {
-    int error = SOCKERRNO;
-    failf(data, "getpeername() failed with errno %d: %s",
-          error, Curl_strerror(error, buffer, sizeof(buffer)));
-    return;
-  }
-  if(!Curl_addr2string((struct sockaddr*)&ssrem, plen,
-                       ctx->ip.remote_ip, &ctx->ip.remote_port)) {
-    failf(data, "ssrem inet_ntop() failed with errno %d: %s",
-          errno, Curl_strerror(errno, buffer, sizeof(buffer)));
-    return;
+  struct Curl_cfilter *cf = data->conn->cfilter[sockindex];
+  while(cf) {
+    if(cf->cft == &Curl_cft_tcp_accept)
+      return TRUE;
+    cf = cf->next;
   }
-#else
-  ctx->ip.remote_ip[0] = 0;
-  ctx->ip.remote_port = 0;
-  (void)data;
-#endif
-}
-
-CURLcode Curl_conn_tcp_accepted_set(struct Curl_easy *data,
-                                    struct connectdata *conn,
-                                    int sockindex, curl_socket_t *s)
-{
-  struct Curl_cfilter *cf = NULL;
-  struct cf_socket_ctx *ctx = NULL;
-
-  cf = conn->cfilter[sockindex];
-  if(!cf || cf->cft != &Curl_cft_tcp_accept)
-    return CURLE_FAILED_INIT;
-
-  ctx = cf->ctx;
-  DEBUGASSERT(ctx->listening);
-  /* discard the listen socket */
-  socket_close(data, conn, TRUE, ctx->sock);
-  ctx->listening = FALSE;
-  ctx->sock = *s;
-  conn->sock[sockindex] = ctx->sock;
-  set_accepted_remote_ip(cf, data);
-  set_local_ip(cf, data);
-  ctx->active = TRUE;
-  ctx->accepted = TRUE;
-  ctx->connected_at = Curl_now();
-  cf->connected = TRUE;
-  CURL_TRC_CF(data, cf, "accepted_set(sock=%" FMT_SOCKET_T
-              ", remote=%s port=%d)",
-              ctx->sock, ctx->ip.remote_ip, ctx->ip.remote_port);
-
-  return CURLE_OK;
+  return FALSE;
 }
 
 /**

+ 5 - 6
lib/cf-socket.h

@@ -52,7 +52,7 @@ struct Curl_sockaddr_ex {
     struct Curl_sockaddr_storage buff;
   } _sa_ex_u;
 };
-#define sa_addr _sa_ex_u.addr
+#define curl_sa_addr _sa_ex_u.addr
 
 /*
  * Parse interface option, and return the interface name and the host part.
@@ -147,12 +147,11 @@ CURLcode Curl_conn_tcp_listen_set(struct Curl_easy *data,
                                   curl_socket_t *s);
 
 /**
- * Replace the listen socket with the accept()ed one.
+ * Return TRUE iff the last filter at `sockindex` was set via
+ * Curl_conn_tcp_listen_set().
  */
-CURLcode Curl_conn_tcp_accepted_set(struct Curl_easy *data,
-                                    struct connectdata *conn,
-                                    int sockindex,
-                                    curl_socket_t *s);
+bool Curl_conn_is_tcp_listen(struct Curl_easy *data,
+                             int sockindex);
 
 /**
  * Peek at the socket and remote ip/port the socket filter is using.

+ 31 - 28
lib/cfilters.c

@@ -96,7 +96,7 @@ void Curl_cf_def_adjust_pollset(struct Curl_cfilter *cf,
 bool Curl_cf_def_data_pending(struct Curl_cfilter *cf,
                               const struct Curl_easy *data)
 {
-  return cf->next?
+  return cf->next ?
     cf->next->cft->has_data_pending(cf->next, data) : FALSE;
 }
 
@@ -104,7 +104,7 @@ ssize_t  Curl_cf_def_send(struct Curl_cfilter *cf, struct Curl_easy *data,
                           const void *buf, size_t len, bool eos,
                           CURLcode *err)
 {
-  return cf->next?
+  return cf->next ?
     cf->next->cft->do_send(cf->next, data, buf, len, eos, err) :
     CURLE_RECV_ERROR;
 }
@@ -112,7 +112,7 @@ ssize_t  Curl_cf_def_send(struct Curl_cfilter *cf, struct Curl_easy *data,
 ssize_t  Curl_cf_def_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
                           char *buf, size_t len, CURLcode *err)
 {
-  return cf->next?
+  return cf->next ?
     cf->next->cft->do_recv(cf->next, data, buf, len, err) :
     CURLE_SEND_ERROR;
 }
@@ -121,7 +121,7 @@ bool Curl_cf_def_conn_is_alive(struct Curl_cfilter *cf,
                                struct Curl_easy *data,
                                bool *input_pending)
 {
-  return cf->next?
+  return cf->next ?
     cf->next->cft->is_alive(cf->next, data, input_pending) :
     FALSE; /* pessimistic in absence of data */
 }
@@ -129,7 +129,7 @@ bool Curl_cf_def_conn_is_alive(struct Curl_cfilter *cf,
 CURLcode Curl_cf_def_conn_keep_alive(struct Curl_cfilter *cf,
                                      struct Curl_easy *data)
 {
-  return cf->next?
+  return cf->next ?
     cf->next->cft->keep_alive(cf->next, data) :
     CURLE_OK;
 }
@@ -138,7 +138,7 @@ CURLcode Curl_cf_def_query(struct Curl_cfilter *cf,
                            struct Curl_easy *data,
                            int query, int *pres1, void *pres2)
 {
-  return cf->next?
+  return cf->next ?
     cf->next->cft->query(cf->next, data, query, pres1, pres2) :
     CURLE_UNKNOWN_OPTION;
 }
@@ -204,13 +204,14 @@ CURLcode Curl_conn_shutdown(struct Curl_easy *data, int sockindex, bool *done)
   now = Curl_now();
   if(!Curl_shutdown_started(data, sockindex)) {
     DEBUGF(infof(data, "shutdown start on%s connection",
-           sockindex? " secondary" : ""));
+           sockindex ? " secondary" : ""));
     Curl_shutdown_start(data, sockindex, &now);
   }
   else {
     timeout_ms = Curl_shutdown_timeleft(data->conn, sockindex, &now);
     if(timeout_ms < 0) {
-      failf(data, "SSL shutdown timeout");
+      /* info message, since this might be regarded as acceptable */
+      infof(data, "shutdown timeout");
       return CURLE_OPERATION_TIMEDOUT;
     }
   }
@@ -483,12 +484,12 @@ bool Curl_conn_cf_is_ssl(struct Curl_cfilter *cf)
 
 bool Curl_conn_is_ssl(struct connectdata *conn, int sockindex)
 {
-  return conn? Curl_conn_cf_is_ssl(conn->cfilter[sockindex]) : FALSE;
+  return conn ? Curl_conn_cf_is_ssl(conn->cfilter[sockindex]) : FALSE;
 }
 
 bool Curl_conn_is_multiplex(struct connectdata *conn, int sockindex)
 {
-  struct Curl_cfilter *cf = conn? conn->cfilter[sockindex] : NULL;
+  struct Curl_cfilter *cf = conn ? conn->cfilter[sockindex] : NULL;
 
   for(; cf; cf = cf->next) {
     if(cf->cft->flags & CF_TYPE_MULTIPLEX)
@@ -522,10 +523,10 @@ bool Curl_conn_cf_needs_flush(struct Curl_cfilter *cf,
                               struct Curl_easy *data)
 {
   CURLcode result;
-  int pending = FALSE;
-  result = cf? cf->cft->query(cf, data, CF_QUERY_NEED_FLUSH,
-                              &pending, NULL) : CURLE_UNKNOWN_OPTION;
-  return (result || pending == FALSE)? FALSE : TRUE;
+  int pending = 0;
+  result = cf ? cf->cft->query(cf, data, CF_QUERY_NEED_FLUSH,
+                               &pending, NULL) : CURLE_UNKNOWN_OPTION;
+  return (result || !pending) ? FALSE : TRUE;
 }
 
 bool Curl_conn_needs_flush(struct Curl_easy *data, int sockindex)
@@ -672,13 +673,13 @@ 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;
+  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;
+  return data->conn ? data->conn->sock[sockindex] : CURL_SOCKET_BAD;
 }
 
 void Curl_conn_forget_socket(struct Curl_easy *data, int sockindex)
@@ -807,7 +808,7 @@ CURLcode Curl_conn_keep_alive(struct Curl_easy *data,
                               int sockindex)
 {
   struct Curl_cfilter *cf = conn->cfilter[sockindex];
-  return cf? cf->cft->keep_alive(cf, data) : CURLE_OK;
+  return cf ? cf->cft->keep_alive(cf, data) : CURLE_OK;
 }
 
 size_t Curl_conn_get_max_concurrent(struct Curl_easy *data,
@@ -818,9 +819,9 @@ size_t Curl_conn_get_max_concurrent(struct Curl_easy *data,
   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;
+  result = cf ? cf->cft->query(cf, data, CF_QUERY_MAX_CONCURRENT,
+                               &n, NULL) : CURLE_UNKNOWN_OPTION;
+  return (result || n <= 0) ? 1 : (size_t)n;
 }
 
 int Curl_conn_get_stream_error(struct Curl_easy *data,
@@ -831,9 +832,9 @@ int Curl_conn_get_stream_error(struct Curl_easy *data,
   int n = 0;
 
   struct Curl_cfilter *cf = conn->cfilter[sockindex];
-  result = cf? cf->cft->query(cf, data, CF_QUERY_STREAM_ERROR,
-                              &n, NULL) : CURLE_UNKNOWN_OPTION;
-  return (result || n < 0)? 0 : n;
+  result = cf ? cf->cft->query(cf, data, CF_QUERY_STREAM_ERROR,
+                               &n, NULL) : CURLE_UNKNOWN_OPTION;
+  return (result || n < 0) ? 0 : n;
 }
 
 int Curl_conn_sockindex(struct Curl_easy *data, curl_socket_t sockfd)
@@ -854,7 +855,7 @@ CURLcode Curl_conn_recv(struct Curl_easy *data, int sockindex,
   nread = data->conn->recv[sockindex](data, sockindex, buf, blen, &result);
   DEBUGASSERT(nread >= 0 || result);
   DEBUGASSERT(nread < 0 || !result);
-  *n = (nread >= 0)? (size_t)nread : 0;
+  *n = (nread >= 0) ? (size_t)nread : 0;
   return result;
 }
 
@@ -889,7 +890,7 @@ CURLcode Curl_conn_send(struct Curl_easy *data, int sockindex,
   nwritten = conn->send[sockindex](data, sockindex, buf, write_len, eos,
                                    &result);
   DEBUGASSERT((nwritten >= 0) || result);
-  *pnwritten = (nwritten < 0)? 0 : (size_t)nwritten;
+  *pnwritten = (nwritten < 0) ? 0 : (size_t)nwritten;
   return result;
 }
 
@@ -899,7 +900,7 @@ void Curl_pollset_reset(struct Curl_easy *data,
   size_t i;
   (void)data;
   memset(ps, 0, sizeof(*ps));
-  for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++)
+  for(i = 0; i < MAX_SOCKSPEREASYHANDLE; i++)
     ps->sockets[i] = CURL_SOCKET_BAD;
 }
 
@@ -961,8 +962,10 @@ void Curl_pollset_set(struct Curl_easy *data,
                       bool do_in, bool do_out)
 {
   Curl_pollset_change(data, ps, sock,
-                      (do_in?CURL_POLL_IN:0)|(do_out?CURL_POLL_OUT:0),
-                      (!do_in?CURL_POLL_IN:0)|(!do_out?CURL_POLL_OUT:0));
+                      (do_in ? CURL_POLL_IN : 0)|
+                      (do_out ? CURL_POLL_OUT : 0),
+                      (!do_in ? CURL_POLL_IN : 0)|
+                      (!do_out ? CURL_POLL_OUT : 0));
 }
 
 static void ps_add(struct Curl_easy *data, struct easy_pollset *ps,

+ 12 - 24
lib/conncache.c

@@ -72,7 +72,7 @@
   } while(0)
 
 
-/* A list of connections to the same destinationn. */
+/* A list of connections to the same destination. */
 struct cpool_bundle {
   struct Curl_llist conns; /* connections in the bundle */
   size_t dest_len; /* total length of destination, including NUL */
@@ -163,16 +163,16 @@ int Curl_cpool_init(struct cpool *cpool,
   cpool->idata = curl_easy_init();
   if(!cpool->idata)
     return 1; /* bad */
-  cpool->idata->state.internal = true;
+  cpool->idata->state.internal = TRUE;
   /* TODO: this is quirky. We need an internal handle for certain
    * operations, but we do not add it to the multi (if there is one).
    * But we give it the multi so that socket event operations can work.
    * Probably better to have an internal handle owned by the multi that
    * can be used for cpool operations. */
   cpool->idata->multi = multi;
- #ifdef DEBUGBUILD
+#ifdef DEBUGBUILD
   if(getenv("CURL_DEBUG"))
-    cpool->idata->set.verbose = true;
+    cpool->idata->set.verbose = TRUE;
 #endif
 
   cpool->disconnect_cb = disconnect_cb;
@@ -269,25 +269,10 @@ cpool_add_bundle(struct cpool *cpool, struct connectdata *conn)
 static void cpool_remove_bundle(struct cpool *cpool,
                                 struct cpool_bundle *bundle)
 {
-  struct Curl_hash_iterator iter;
-  struct Curl_hash_element *he;
-
   if(!cpool)
     return;
 
-  Curl_hash_start_iterate(&cpool->dest2bundle, &iter);
-
-  he = Curl_hash_next_element(&iter);
-  while(he) {
-    if(he->ptr == bundle) {
-      /* The bundle is destroyed by the hash destructor function,
-         free_bundle_hash_entry() */
-      Curl_hash_delete(&cpool->dest2bundle, he->key, he->key_len);
-      return;
-    }
-
-    he = Curl_hash_next_element(&iter);
-  }
+  Curl_hash_delete(&cpool->dest2bundle, bundle->dest, bundle->dest_len);
 }
 
 static struct connectdata *
@@ -329,6 +314,9 @@ int Curl_cpool_check_limits(struct Curl_easy *data,
                    "limit of %zu", oldest_idle->connection_id,
                    Curl_llist_count(&bundle->conns), dest_limit));
       Curl_cpool_disconnect(data, oldest_idle, FALSE);
+
+      /* in case the bundle was destroyed in disconnect, look it up again */
+      bundle = cpool_find_bundle(cpool, conn);
     }
     if(bundle && (Curl_llist_count(&bundle->conns) >= dest_limit)) {
       result = CPOOL_LIMIT_DEST;
@@ -409,7 +397,7 @@ static void cpool_remove_conn(struct cpool *cpool,
       cpool->num_conn--;
     }
     else {
-      /* Not in  a bundle, already in the shutdown list? */
+      /* Not in a bundle, already in the shutdown list? */
       DEBUGASSERT(list == &cpool->shutdowns);
     }
   }
@@ -491,7 +479,7 @@ bool Curl_cpool_conn_now_idle(struct Curl_easy *data,
                               struct connectdata *conn)
 {
   unsigned int maxconnects = !data->multi->maxconnects ?
-    data->multi->num_easy * 4: data->multi->maxconnects;
+    data->multi->num_easy * 4 : data->multi->maxconnects;
   struct connectdata *oldest_idle = NULL;
   struct cpool *cpool = cpool_get_instance(data);
   bool kept = TRUE;
@@ -820,7 +808,7 @@ void Curl_cpool_disconnect(struct Curl_easy *data,
   if(data->multi) {
     /* Add it to the multi's cpool for shutdown handling */
     infof(data, "%s connection #%" FMT_OFF_T,
-          aborted? "closing" : "shutting down", conn->connection_id);
+          aborted ? "closing" : "shutting down", conn->connection_id);
     cpool_discard_conn(&data->multi->cpool, data, conn, aborted);
   }
   else {
@@ -1180,7 +1168,7 @@ static void cpool_shutdown_all(struct cpool *cpool,
     timespent = Curl_timediff(Curl_now(), started);
     if(timespent >= (timediff_t)timeout_ms) {
       DEBUGF(infof(data, "cpool shutdown %s",
-                   (timeout_ms > 0)? "timeout" : "best effort done"));
+                   (timeout_ms > 0) ? "timeout" : "best effort done"));
       break;
     }
 

+ 8 - 8
lib/connect.c

@@ -139,7 +139,7 @@ timediff_t Curl_timeleft(struct Curl_easy *data,
       return ctimeleft_ms; /* no general timeout, this is it */
   }
   /* return minimal time left or max amount already expired */
-  return (ctimeleft_ms < timeleft_ms)? ctimeleft_ms : timeleft_ms;
+  return (ctimeleft_ms < timeleft_ms) ? ctimeleft_ms : timeleft_ms;
 }
 
 void Curl_shutdown_start(struct Curl_easy *data, int sockindex,
@@ -172,7 +172,7 @@ timediff_t Curl_shutdown_timeleft(struct connectdata *conn, int sockindex,
   }
   left_ms = conn->shutdown.timeout_ms -
             Curl_timediff(*nowp, conn->shutdown.start[sockindex]);
-  return left_ms? left_ms : -1;
+  return left_ms ? left_ms : -1;
 }
 
 timediff_t Curl_conn_shutdown_timeleft(struct connectdata *conn,
@@ -414,9 +414,9 @@ static CURLcode eyeballer_new(struct eyeballer **pballer,
   if(!baller)
     return CURLE_OUT_OF_MEMORY;
 
-  baller->name = ((ai_family == AF_INET)? "ipv4" : (
+  baller->name = ((ai_family == AF_INET) ? "ipv4" : (
 #ifdef USE_IPV6
-                  (ai_family == AF_INET6)? "ipv6" :
+                  (ai_family == AF_INET6) ? "ipv6" :
 #endif
                   "ip"));
   baller->cf_create = cf_create;
@@ -424,7 +424,7 @@ static CURLcode eyeballer_new(struct eyeballer **pballer,
   baller->ai_family = ai_family;
   baller->primary = primary;
   baller->delay_ms = delay_ms;
-  baller->timeoutms = addr_next_match(baller->addr, baller->ai_family)?
+  baller->timeoutms = addr_next_match(baller->addr, baller->ai_family) ?
     USETIME(timeout_ms) : timeout_ms;
   baller->timeout_id = timeout_id;
   baller->result = CURLE_COULDNT_CONNECT;
@@ -619,7 +619,7 @@ static CURLcode is_connected(struct Curl_cfilter *cf,
    * If transport is QUIC, we need to shutdown the ongoing 'other'
    * cot ballers in a QUIC appropriate way. */
 evaluate:
-  *connected = FALSE; /* a very negative world view is best */
+  *connected = FALSE; /* a negative world view is best */
   now = Curl_now();
   ongoing = not_started = 0;
   for(i = 0; i < ARRAYSIZE(ctx->baller); i++) {
@@ -1089,7 +1089,7 @@ static CURLcode cf_he_query(struct Curl_cfilter *cf,
     }
   }
 
-  return cf->next?
+  return cf->next ?
     cf->next->cft->query(cf->next, data, query, pres1, pres2) :
     CURLE_UNKNOWN_OPTION;
 }
@@ -1417,7 +1417,7 @@ static CURLcode cf_setup_create(struct Curl_cfilter **pcf,
   ctx = NULL;
 
 out:
-  *pcf = result? NULL : cf;
+  *pcf = result ? NULL : cf;
   free(ctx);
   return result;
 }

+ 8 - 8
lib/content_encoding.c

@@ -33,13 +33,13 @@
 #endif
 
 #ifdef HAVE_BROTLI
-#if defined(__GNUC__)
+#if defined(__GNUC__) || defined(__clang__)
 /* Ignore -Wvla warnings in brotli headers */
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wvla"
 #endif
 #include <brotli/decode.h>
-#if defined(__GNUC__)
+#if defined(__GNUC__) || defined(__clang__)
 #pragma GCC diagnostic pop
 #endif
 #endif
@@ -154,7 +154,7 @@ static CURLcode process_trailer(struct Curl_easy *data,
 {
   z_stream *z = &zp->z;
   CURLcode result = CURLE_OK;
-  uInt len = z->avail_in < zp->trailerlen? z->avail_in: zp->trailerlen;
+  uInt len = z->avail_in < zp->trailerlen ? z->avail_in : zp->trailerlen;
 
   /* Consume expected trailer bytes. Terminate stream if exhausted.
      Issue an error if unexpected bytes follow. */
@@ -654,7 +654,7 @@ static CURLcode brotli_do_init(struct Curl_easy *data,
   (void) data;
 
   bp->br = BrotliDecoderCreateInstance(NULL, NULL, NULL);
-  return bp->br? CURLE_OK: CURLE_OUT_OF_MEMORY;
+  return bp->br ? CURLE_OK : CURLE_OUT_OF_MEMORY;
 }
 
 static CURLcode brotli_do_write(struct Curl_easy *data,
@@ -971,8 +971,8 @@ static const struct Curl_cwtype *find_unencode_writer(const char *name,
 CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
                                      const char *enclist, int is_transfer)
 {
-  Curl_cwriter_phase phase = is_transfer?
-                             CURL_CW_TRANSFER_DECODE:CURL_CW_CONTENT_DECODE;
+  Curl_cwriter_phase phase = is_transfer ?
+    CURL_CW_TRANSFER_DECODE : CURL_CW_CONTENT_DECODE;
   CURLcode result;
 
   do {
@@ -995,7 +995,7 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
       struct Curl_cwriter *writer;
 
       CURL_TRC_WRITE(data, "looking for %s decoder: %.*s",
-                     is_transfer? "transfer" : "content", (int)namelen, name);
+                     is_transfer ? "transfer" : "content", (int)namelen, name);
       is_chunked = (is_transfer && (namelen == 7) &&
                     strncasecompare(name, "chunked", 7));
       /* if we skip the decoding in this phase, do not look further.
@@ -1046,7 +1046,7 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data,
 
       result = Curl_cwriter_create(&writer, data, cwt, phase);
       CURL_TRC_WRITE(data, "added %s decoder %s -> %d",
-                     is_transfer? "transfer" : "content", cwt->name, result);
+                     is_transfer ? "transfer" : "content", cwt->name, result);
       if(result)
         return result;
 

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 450 - 537
lib/cookie.c


+ 21 - 17
lib/cookie.h

@@ -27,20 +27,24 @@
 
 #include <curl/curl.h>
 
+#include "llist.h"
+
 struct Cookie {
-  struct Cookie *next; /* next in the chain */
-  char *name;        /* <this> = value */
-  char *value;       /* name = <this> */
+  struct Curl_llist_node node; /* for the main cookie list */
+  struct Curl_llist_node getnode; /* for getlist */
+  char *name;         /* <this> = value */
+  char *value;        /* name = <this> */
   char *path;         /* path = <this> which is in Set-Cookie: */
   char *spath;        /* sanitized cookie path */
-  char *domain;      /* domain = <this> */
-  curl_off_t expires;  /* expires = <this> */
-  bool tailmatch;    /* whether we do tail-matching of the domain name */
-  bool secure;       /* whether the 'secure' keyword was used */
-  bool livecookie;   /* updated from a server, not a stored file */
-  bool httponly;     /* true if the httponly directive is present */
-  int creationtime;  /* time when the cookie was written */
-  unsigned char prefix; /* bitmap fields indicating which prefix are set */
+  char *domain;       /* domain = <this> */
+  curl_off_t expires; /* expires = <this> */
+  int creationtime;   /* time when the cookie was written */
+  BIT(tailmatch);     /* tail-match the domain name */
+  BIT(secure);        /* the 'secure' keyword was used */
+  BIT(livecookie);    /* updated from a server, not a stored file */
+  BIT(httponly);      /* the httponly directive is present */
+  BIT(prefix_secure); /* secure prefix is set */
+  BIT(prefix_host);   /* host prefix is set */
 };
 
 /*
@@ -53,8 +57,8 @@ struct Cookie {
 #define COOKIE_HASH_SIZE 63
 
 struct CookieInfo {
-  /* linked list of cookies we know of */
-  struct Cookie *cookies[COOKIE_HASH_SIZE];
+  /* linked lists of cookies we know of */
+  struct Curl_llist cookielist[COOKIE_HASH_SIZE];
   curl_off_t next_expiration; /* the next time at which expiration happens */
   int numcookies;  /* number of cookies in the "jar" */
   int lastct;      /* last creation-time used in the jar */
@@ -112,10 +116,10 @@ struct Cookie *Curl_cookie_add(struct Curl_easy *data,
                                const char *domain, const char *path,
                                bool secure);
 
-struct Cookie *Curl_cookie_getlist(struct Curl_easy *data,
-                                   struct CookieInfo *c, const char *host,
-                                   const char *path, bool secure);
-void Curl_cookie_freelist(struct Cookie *cookies);
+int Curl_cookie_getlist(struct Curl_easy *data,
+                        struct CookieInfo *c, const char *host,
+                        const char *path, bool secure,
+                        struct Curl_llist *list);
 void Curl_cookie_clearall(struct CookieInfo *cookies);
 void Curl_cookie_clearsess(struct CookieInfo *cookies);
 

+ 46 - 60
lib/curl_addrinfo.c

@@ -252,6 +252,7 @@ Curl_getaddrinfo_ex(const char *nodename,
  *     #define h_addr  h_addr_list[0]
  */
 
+#if !(defined(HAVE_GETADDRINFO) && defined(HAVE_GETADDRINFO_THREADSAFE))
 struct Curl_addrinfo *
 Curl_he2ai(const struct hostent *he, int port)
 {
@@ -350,19 +351,7 @@ Curl_he2ai(const struct hostent *he, int port)
 
   return firstai;
 }
-
-
-struct namebuff {
-  struct hostent hostentry;
-  union {
-    struct in_addr  ina4;
-#ifdef USE_IPV6
-    struct in6_addr ina6;
 #endif
-  } addrentry;
-  char *h_addr_list[2];
-};
-
 
 /*
  * Curl_ip2addr()
@@ -377,71 +366,68 @@ struct Curl_addrinfo *
 Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port)
 {
   struct Curl_addrinfo *ai;
-
-#if defined(__VMS) && \
-    defined(__INITIAL_POINTER_SIZE) && (__INITIAL_POINTER_SIZE == 64)
-#pragma pointer_size save
-#pragma pointer_size short
-#pragma message disable PTRMISMATCH
-#endif
-
-  struct hostent  *h;
-  struct namebuff *buf;
-  char  *addrentry;
-  char  *hoststr;
   size_t addrsize;
+  size_t namelen;
+  struct sockaddr_in *addr;
+#ifdef USE_IPV6
+  struct sockaddr_in6 *addr6;
+#endif
 
   DEBUGASSERT(inaddr && hostname);
 
-  buf = malloc(sizeof(struct namebuff));
-  if(!buf)
+  namelen = strlen(hostname) + 1;
+
+  if(af == AF_INET)
+    addrsize = sizeof(struct sockaddr_in);
+#ifdef USE_IPV6
+  else if(af == AF_INET6)
+    addrsize = sizeof(struct sockaddr_in6);
+#endif
+  else
     return NULL;
 
-  hoststr = strdup(hostname);
-  if(!hoststr) {
-    free(buf);
+  /* allocate memory to hold the struct, the address and the name */
+  ai = calloc(1, sizeof(struct Curl_addrinfo) + addrsize + namelen);
+  if(!ai)
     return NULL;
-  }
+  /* put the address after the struct */
+  ai->ai_addr = (void *)((char *)ai + sizeof(struct Curl_addrinfo));
+  /* then put the name after the address */
+  ai->ai_canonname = (char *)ai->ai_addr + addrsize;
+  memcpy(ai->ai_canonname, hostname, namelen);
+  ai->ai_family = af;
+  ai->ai_socktype = SOCK_STREAM;
+  ai->ai_addrlen = (curl_socklen_t)addrsize;
+  /* leave the rest of the struct filled with zero */
 
   switch(af) {
   case AF_INET:
-    addrsize = sizeof(struct in_addr);
-    addrentry = (void *)&buf->addrentry.ina4;
-    memcpy(addrentry, inaddr, sizeof(struct in_addr));
+    addr = (void *)ai->ai_addr; /* storage area for this info */
+
+    memcpy(&addr->sin_addr, inaddr, sizeof(struct in_addr));
+#ifdef __MINGW32__
+    addr->sin_family = (short)af;
+#else
+    addr->sin_family = (CURL_SA_FAMILY_T)af;
+#endif
+    addr->sin_port = htons((unsigned short)port);
     break;
+
 #ifdef USE_IPV6
   case AF_INET6:
-    addrsize = sizeof(struct in6_addr);
-    addrentry = (void *)&buf->addrentry.ina6;
-    memcpy(addrentry, inaddr, sizeof(struct in6_addr));
+    addr6 = (void *)ai->ai_addr; /* storage area for this info */
+
+    memcpy(&addr6->sin6_addr, inaddr, sizeof(struct in6_addr));
+#ifdef __MINGW32__
+    addr6->sin6_family = (short)af;
+#else
+    addr6->sin6_family = (CURL_SA_FAMILY_T)af;
+#endif
+    addr6->sin6_port = htons((unsigned short)port);
     break;
 #endif
-  default:
-    free(hoststr);
-    free(buf);
-    return NULL;
   }
 
-  h = &buf->hostentry;
-  h->h_name = hoststr;
-  h->h_aliases = NULL;
-  h->h_addrtype = (short)af;
-  h->h_length = (short)addrsize;
-  h->h_addr_list = &buf->h_addr_list[0];
-  h->h_addr_list[0] = addrentry;
-  h->h_addr_list[1] = NULL; /* terminate list of entries */
-
-#if defined(__VMS) && \
-    defined(__INITIAL_POINTER_SIZE) && (__INITIAL_POINTER_SIZE == 64)
-#pragma pointer_size restore
-#pragma message enable PTRMISMATCH
-#endif
-
-  ai = Curl_he2ai(h, port);
-
-  free(hoststr);
-  free(buf);
-
   return ai;
 }
 

+ 2 - 0
lib/curl_addrinfo.h

@@ -71,8 +71,10 @@ Curl_getaddrinfo_ex(const char *nodename,
                     struct Curl_addrinfo **result);
 #endif
 
+#if !(defined(HAVE_GETADDRINFO) && defined(HAVE_GETADDRINFO_THREADSAFE))
 struct Curl_addrinfo *
 Curl_he2ai(const struct hostent *he, int port);
+#endif
 
 struct Curl_addrinfo *
 Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port);

+ 34 - 20
lib/curl_config.h.cmake

@@ -21,7 +21,6 @@
  * SPDX-License-Identifier: curl
  *
  ***************************************************************************/
-/* lib/curl_config.h.in. Generated somehow by cmake.  */
 
 /* Location of default ca bundle */
 #cmakedefine CURL_CA_BUNDLE "${CURL_CA_BUNDLE}"
@@ -56,7 +55,7 @@
 /* disables negotiate authentication */
 #cmakedefine CURL_DISABLE_NEGOTIATE_AUTH 1
 
-/* disables AWS-SIG4 */
+/* disables aws-sigv4 */
 #cmakedefine CURL_DISABLE_AWS 1
 
 /* disables DICT */
@@ -131,6 +130,9 @@
 /* disables proxies */
 #cmakedefine CURL_DISABLE_PROXY 1
 
+/* disables IPFS from the curl tool */
+#cmakedefine CURL_DISABLE_IPFS 1
+
 /* disables RTSP */
 #cmakedefine CURL_DISABLE_RTSP 1
 
@@ -146,6 +148,9 @@
 /* disables SMTP */
 #cmakedefine CURL_DISABLE_SMTP 1
 
+/* disabled WebSockets */
+#cmakedefine CURL_DISABLE_WEBSOCKETS 1
+
 /* disables use of socketpair for curl_multi_poll */
 #cmakedefine CURL_DISABLE_SOCKETPAIR 1
 
@@ -158,6 +163,12 @@
 /* disables verbose strings */
 #cmakedefine CURL_DISABLE_VERBOSE_STRINGS 1
 
+/* disables unsafe CA bundle search on Windows from the curl tool */
+#cmakedefine CURL_DISABLE_CA_SEARCH 1
+
+/* safe CA bundle search (within the curl tool directory) on Windows */
+#cmakedefine CURL_CA_SEARCH_SAFE 1
+
 /* to make a symbol visible */
 #cmakedefine CURL_EXTERN_SYMBOL ${CURL_EXTERN_SYMBOL}
 /* Ensure using CURL_EXTERN_SYMBOL is possible */
@@ -208,6 +219,9 @@
 /* Define to 1 if you have the `closesocket' function. */
 #cmakedefine HAVE_CLOSESOCKET 1
 
+/* Define to 1 if you have the `CloseSocket' function. */
+#cmakedefine HAVE_CLOSESOCKET_CAMEL 1
+
 /* Define to 1 if you have the <dirent.h> header file. */
 #cmakedefine HAVE_DIRENT_H 1
 
@@ -232,9 +246,6 @@
 /* Define to 1 if you have the fseeko declaration. */
 #cmakedefine HAVE_DECL_FSEEKO 1
 
-/* Define to 1 if you have the _fseeki64 function. */
-#cmakedefine HAVE__FSEEKI64 1
-
 /* Define to 1 if you have the ftruncate function. */
 #cmakedefine HAVE_FTRUNCATE 1
 
@@ -307,9 +318,6 @@
 /* Define to 1 if you have the <gssapi/gssapi.h> header file. */
 #cmakedefine HAVE_GSSAPI_GSSAPI_H 1
 
-/* Define to 1 if you have the <gssapi/gssapi_krb5.h> header file. */
-#cmakedefine HAVE_GSSAPI_GSSAPI_KRB5_H 1
-
 /* if you have the GNU gssapi libraries */
 #cmakedefine HAVE_GSSGNU 1
 
@@ -353,9 +361,6 @@
 /* Define to 1 if you have the lber.h header file. */
 #cmakedefine HAVE_LBER_H 1
 
-/* Define to 1 if you have the ldap.h header file. */
-#cmakedefine HAVE_LDAP_H 1
-
 /* Use LDAPS implementation */
 #cmakedefine HAVE_LDAP_SSL 1
 
@@ -401,6 +406,9 @@
 /* Define to 1 if you have the <netinet/in.h> header file. */
 #cmakedefine HAVE_NETINET_IN_H 1
 
+/* Define to 1 if you have the <netinet/in6.h> header file. */
+#cmakedefine HAVE_NETINET_IN6_H 1
+
 /* Define to 1 if you have the <netinet/tcp.h> header file. */
 #cmakedefine HAVE_NETINET_TCP_H 1
 
@@ -422,8 +430,8 @@
 /* Define to 1 if you have the `eventfd' function. */
 #cmakedefine HAVE_EVENTFD 1
 
-/* If you have a fine poll */
-#cmakedefine HAVE_POLL_FINE 1
+/* If you have poll */
+#cmakedefine HAVE_POLL 1
 
 /* Define to 1 if you have the <poll.h> header file. */
 #cmakedefine HAVE_POLL_H 1
@@ -455,6 +463,9 @@
 /* Define to 1 if you have the sendmsg function. */
 #cmakedefine HAVE_SENDMSG 1
 
+/* Define to 1 if you have the sendmmsg function. */
+#cmakedefine HAVE_SENDMMSG 1
+
 /* Define to 1 if you have the 'fsetxattr' function. */
 #cmakedefine HAVE_FSETXATTR 1
 
@@ -470,6 +481,9 @@
 /* Define to 1 if you have the `setmode' function. */
 #cmakedefine HAVE_SETMODE 1
 
+/* Define to 1 if you have the `_setmode' function. */
+#cmakedefine HAVE__SETMODE 1
+
 /* Define to 1 if you have the `setrlimit' function. */
 #cmakedefine HAVE_SETRLIMIT 1
 
@@ -497,6 +511,9 @@
 /* Define to 1 if you have the `socket' function. */
 #cmakedefine HAVE_SOCKET 1
 
+/* Define to 1 if you have the <proto/bsdsocket.h> header file. */
+#cmakedefine HAVE_PROTO_BSDSOCKET_H 1
+
 /* Define to 1 if you have the socketpair function. */
 #cmakedefine HAVE_SOCKETPAIR 1
 
@@ -608,9 +625,6 @@
 /* Define this symbol if your OS supports changing the contents of argv */
 #cmakedefine HAVE_WRITABLE_ARGV 1
 
-/* Define to 1 if you need the lber.h header file even with ldap.h */
-#cmakedefine NEED_LBER_H 1
-
 /* Define to 1 if you need the malloc.h header file even with stdlib.h */
 #cmakedefine NEED_MALLOC_H 1
 
@@ -618,7 +632,7 @@
 #cmakedefine NEED_REENTRANT 1
 
 /* cpu-machine-OS */
-#cmakedefine OS ${OS}
+#cmakedefine CURL_OS ${CURL_OS}
 
 /* Name of package */
 #cmakedefine PACKAGE ${PACKAGE}
@@ -704,6 +718,9 @@ ${SIZEOF_TIME_T_CODE}
 /* if wolfSSL has the wolfSSL_DES_ecb_encrypt function. */
 #cmakedefine HAVE_WOLFSSL_DES_ECB_ENCRYPT 1
 
+/* if wolfSSL has the wolfSSL_BIO_new function. */
+#cmakedefine HAVE_WOLFSSL_BIO 1
+
 /* if wolfSSL has the wolfSSL_BIO_set_shutdown function. */
 #cmakedefine HAVE_WOLFSSL_FULL_BIO 1
 
@@ -810,9 +827,6 @@ ${SIZEOF_TIME_T_CODE}
 /* to enable Apple IDN */
 #cmakedefine USE_APPLE_IDN 1
 
-/* Define to 1 to enable websocket support. */
-#cmakedefine USE_WEBSOCKETS 1
-
 /* Define to 1 if OpenSSL has the SSL_CTX_set_srp_username function. */
 #cmakedefine HAVE_OPENSSL_SRP 1
 

+ 3 - 3
lib/curl_fnmatch.c

@@ -161,7 +161,7 @@ static void setcharorrange(unsigned char **pp, unsigned char *charset)
   }
 }
 
-/* returns 1 (true) if pattern is OK, 0 if is bad ("p" is pattern pointer) */
+/* returns 1 (TRUE) if pattern is OK, 0 if is bad ("p" is pattern pointer) */
 static int setcharset(unsigned char **p, unsigned char *charset)
 {
   setcharset_state state = CURLFNM_SCHS_DEFAULT;
@@ -293,7 +293,7 @@ static int loop(const unsigned char *pattern, const unsigned char *string,
       p++;
       break;
     case '\0':
-      return *s? CURL_FNMATCH_NOMATCH: CURL_FNMATCH_MATCH;
+      return *s ? CURL_FNMATCH_NOMATCH : CURL_FNMATCH_MATCH;
     case '\\':
       if(p[1])
         p++;
@@ -303,7 +303,7 @@ static int loop(const unsigned char *pattern, const unsigned char *string,
     case '[':
       pp = p + 1; /* Copy in case of syntax error in set. */
       if(setcharset(&pp, charset)) {
-        int found = FALSE;
+        bool found = FALSE;
         if(!*s)
           return CURL_FNMATCH_NOMATCH;
         if(charset[(unsigned int)*s])

+ 1 - 1
lib/curl_gssapi.c

@@ -35,7 +35,7 @@
 #include "memdebug.h"
 
 #if defined(__GNUC__)
-#define CURL_ALIGN8   __attribute__ ((aligned(8)))
+#define CURL_ALIGN8  __attribute__((aligned(8)))
 #else
 #define CURL_ALIGN8
 #endif

+ 14 - 16
lib/curl_hmac.h

@@ -32,30 +32,28 @@
 
 #define HMAC_MD5_LENGTH 16
 
-typedef CURLcode (* HMAC_hinit_func)(void *context);
-typedef void    (* HMAC_hupdate_func)(void *context,
-                                      const unsigned char *data,
-                                      unsigned int len);
-typedef void    (* HMAC_hfinal_func)(unsigned char *result, void *context);
-
+typedef CURLcode (*HMAC_hinit)(void *context);
+typedef void    (*HMAC_hupdate)(void *context,
+                                const unsigned char *data,
+                                unsigned int len);
+typedef void    (*HMAC_hfinal)(unsigned char *result, void *context);
 
 /* Per-hash function HMAC parameters. */
 struct HMAC_params {
-  HMAC_hinit_func
-  hmac_hinit;     /* Initialize context procedure. */
-  HMAC_hupdate_func     hmac_hupdate;   /* Update context with data. */
-  HMAC_hfinal_func      hmac_hfinal;    /* Get final result procedure. */
-  unsigned int          hmac_ctxtsize;  /* Context structure size. */
-  unsigned int          hmac_maxkeylen; /* Maximum key length (bytes). */
-  unsigned int          hmac_resultlen; /* Result length (bytes). */
+  HMAC_hinit       hinit;     /* Initialize context procedure. */
+  HMAC_hupdate     hupdate;   /* Update context with data. */
+  HMAC_hfinal      hfinal;    /* Get final result procedure. */
+  unsigned int     ctxtsize;  /* Context structure size. */
+  unsigned int     maxkeylen; /* Maximum key length (bytes). */
+  unsigned int     resultlen; /* Result length (bytes). */
 };
 
 
 /* HMAC computation context. */
 struct HMAC_context {
-  const struct HMAC_params *hmac_hash; /* Hash function definition. */
-  void *hmac_hashctxt1;         /* Hash function context 1. */
-  void *hmac_hashctxt2;         /* Hash function context 2. */
+  const struct HMAC_params *hash; /* Hash function definition. */
+  void *hashctxt1;         /* Hash function context 1. */
+  void *hashctxt2;         /* Hash function context 2. */
 };
 
 

+ 7 - 7
lib/curl_md5.h

@@ -31,11 +31,11 @@
 
 #define MD5_DIGEST_LEN  16
 
-typedef CURLcode (* Curl_MD5_init_func)(void *context);
-typedef void (* Curl_MD5_update_func)(void *context,
-                                      const unsigned char *data,
-                                      unsigned int len);
-typedef void (* Curl_MD5_final_func)(unsigned char *result, void *context);
+typedef CURLcode (*Curl_MD5_init_func)(void *context);
+typedef void (*Curl_MD5_update_func)(void *context,
+                                     const unsigned char *data,
+                                     unsigned int len);
+typedef void (*Curl_MD5_final_func)(unsigned char *result, void *context);
 
 struct MD5_params {
   Curl_MD5_init_func     md5_init_func;   /* Initialize context procedure */
@@ -50,8 +50,8 @@ struct MD5_context {
   void                  *md5_hashctx;   /* Hash function context */
 };
 
-extern const struct MD5_params Curl_DIGEST_MD5[1];
-extern const struct HMAC_params Curl_HMAC_MD5[1];
+extern const struct MD5_params Curl_DIGEST_MD5;
+extern const struct HMAC_params Curl_HMAC_MD5;
 
 CURLcode Curl_md5it(unsigned char *output, const unsigned char *input,
                     const size_t len);

+ 2 - 0
lib/curl_memory.h

@@ -84,6 +84,7 @@
 #undef socketpair
 #endif
 
+#ifndef CURL_NO_GETADDRINFO_OVERRIDE
 #ifdef HAVE_GETADDRINFO
 #if defined(getaddrinfo) && defined(__osf__)
 #undef ogetaddrinfo
@@ -95,6 +96,7 @@
 #ifdef HAVE_FREEADDRINFO
 #undef freeaddrinfo
 #endif /* HAVE_FREEADDRINFO */
+#endif /* !CURL_NO_GETADDRINFO_OVERRIDE */
 
 /* sclose is probably already defined, redefine it! */
 #undef sclose

+ 23 - 11
lib/curl_ntlm_core.c

@@ -71,13 +71,6 @@
 #  include <openssl/md5.h>
 #  include <openssl/ssl.h>
 #  include <openssl/rand.h>
-#else
-#  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
@@ -95,6 +88,25 @@
 #    define DESKEYARG(x) *x
 #    define DESKEY(x) &x
 #  endif
+#else
+#  include <wolfssl/openssl/des.h>
+#  include <wolfssl/openssl/md5.h>
+#  include <wolfssl/openssl/ssl.h>
+#  include <wolfssl/openssl/rand.h>
+#  if defined(OPENSSL_COEXIST)
+#    define DES_key_schedule WOLFSSL_DES_key_schedule
+#    define DES_cblock WOLFSSL_DES_cblock
+#    define DES_set_odd_parity wolfSSL_DES_set_odd_parity
+#    define DES_set_key wolfSSL_DES_set_key
+#    define DES_set_key_unchecked wolfSSL_DES_set_key_unchecked
+#    define DES_ecb_encrypt wolfSSL_DES_ecb_encrypt
+#    define DESKEY(x) ((WOLFSSL_DES_key_schedule *)(x))
+#    define DESKEYARG(x) *x
+#  else
+#    define DESKEYARG(x) *x
+#    define DESKEY(x) &x
+#  endif
+#endif
 
 #elif defined(USE_GNUTLS)
 
@@ -483,7 +495,7 @@ static void time2filetime(struct ms_filetime *ft, time_t t)
      134774 days = 11644473600 seconds = 0x2B6109100 */
   r = ft->dwLowDateTime;
   ft->dwLowDateTime = (ft->dwLowDateTime + 0xB6109100U) & 0xFFFFFFFF;
-  ft->dwHighDateTime += ft->dwLowDateTime < r? 0x03: 0x02;
+  ft->dwHighDateTime += ft->dwLowDateTime < r ? 0x03 : 0x02;
 
   /* Convert to tenths of microseconds. */
   ft->dwHighDateTime *= 10000000;
@@ -528,7 +540,7 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen,
   ascii_uppercase_to_unicode_le(identity, user, userlen);
   ascii_to_unicode_le(identity + (userlen << 1), domain, domlen);
 
-  result = Curl_hmacit(Curl_HMAC_MD5, ntlmhash, 16, identity, identity_len,
+  result = Curl_hmacit(&Curl_HMAC_MD5, ntlmhash, 16, identity, identity_len,
                        ntlmv2hash);
   free(identity);
 
@@ -613,7 +625,7 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
 
   /* Concatenate the Type 2 challenge with the BLOB and do HMAC MD5 */
   memcpy(ptr + 8, &ntlm->nonce[0], 8);
-  result = Curl_hmacit(Curl_HMAC_MD5, ntlmv2hash, HMAC_MD5_LENGTH, ptr + 8,
+  result = Curl_hmacit(&Curl_HMAC_MD5, ntlmv2hash, HMAC_MD5_LENGTH, ptr + 8,
                     NTLMv2_BLOB_LEN + 8, hmac_output);
   if(result) {
     free(ptr);
@@ -656,7 +668,7 @@ CURLcode  Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash,
   memcpy(&data[0], challenge_server, 8);
   memcpy(&data[8], challenge_client, 8);
 
-  result = Curl_hmacit(Curl_HMAC_MD5, ntlmv2hash, 16, &data[0], 16,
+  result = Curl_hmacit(&Curl_HMAC_MD5, ntlmv2hash, 16, &data[0], 16,
                        hmac_output);
   if(result)
     return result;

+ 1 - 1
lib/curl_rtmp.c

@@ -255,7 +255,7 @@ static CURLcode rtmp_connect(struct Curl_easy *data, bool *done)
     return CURLE_FAILED_INIT;
 
   /* Clients must send a periodic BytesReceived report to the server */
-  r->m_bSendCounter = true;
+  r->m_bSendCounter = TRUE;
 
   *done = TRUE;
   conn->recv[FIRSTSOCKET] = rtmp_recv;

+ 33 - 11
lib/curl_setup.h

@@ -33,7 +33,7 @@
 
 /* FIXME: Delete this once the warnings have been fixed. */
 #if !defined(CURL_WARN_SIGN_CONVERSION)
-#ifdef __GNUC__
+#if defined(__GNUC__) || defined(__clang__)
 #pragma GCC diagnostic ignored "-Wsign-conversion"
 #endif
 #endif
@@ -43,21 +43,24 @@
 #include <_mingw.h>
 #endif
 
-/* Workaround for Homebrew gcc 12.4.0, 13.3.0, 14.1.0 and newer (as of 14.1.0)
+/* Workaround for Homebrew gcc 12.4.0, 13.3.0, 14.1.0, 14.2.0 (initial build)
    that started advertising the `availability` attribute, which then gets used
-   by Apple SDK, but, in a way incompatible with gcc, resulting in a misc
-   errors inside SDK headers, e.g.:
+   by Apple SDK, but, in a way incompatible with gcc, resulting in misc errors
+   inside SDK headers, e.g.:
      error: attributes should be specified before the declarator in a function
             definition
      error: expected ',' or '}' before
    Followed by missing declarations.
-   Fix it by overriding the built-in feature-check macro used by the headers
-   to enable the problematic attributes. This makes the feature check fail. */
-#if defined(__APPLE__) &&                \
-  !defined(__clang__) &&                 \
-  defined(__GNUC__) && __GNUC__ >= 12 && \
+   Work it around by overriding the built-in feature-check macro used by the
+   headers to enable the problematic attributes. This makes the feature check
+   fail. Fixed in 14.2.0_1. Disable the workaround if the fix is detected. */
+#if defined(__APPLE__) && !defined(__clang__) && defined(__GNUC__) && \
   defined(__has_attribute)
-#define availability curl_pp_attribute_disabled
+#  if !defined(__has_feature)
+#    define availability curl_pp_attribute_disabled
+#  elif !__has_feature(attribute_availability)
+#    define availability curl_pp_attribute_disabled
+#  endif
 #endif
 
 #if defined(__APPLE__)
@@ -109,7 +112,7 @@
 #  include <winapifamily.h>
 #  if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) &&  \
      !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
-#    define CURL_WINDOWS_APP
+#    define CURL_WINDOWS_UWP
 #  endif
 # endif
 #endif
@@ -208,6 +211,11 @@
 /*  please, do it beyond the point further indicated in this file.  */
 /* ================================================================ */
 
+/* Give calloc a chance to be dragging in early, so we do not redefine */
+#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
+#  include <pthread.h>
+#endif
+
 /*
  * Disable other protocols when http is the only one desired.
  */
@@ -282,6 +290,14 @@
 #  define CURL_DISABLE_HTTP_AUTH 1
 #endif
 
+/*
+ * ECH requires HTTPSRR.
+ */
+
+#if defined(USE_ECH) && !defined(USE_HTTPSRR)
+#  define USE_HTTPSRR
+#endif
+
 /* ================================================================ */
 /* No system header file shall be included in this file before this */
 /* point.                                                           */
@@ -449,6 +465,12 @@
 #include <curl/stdcheaders.h>
 #endif
 
+#ifdef _WIN32
+#define Curl_getpid() GetCurrentProcessId()
+#else
+#define Curl_getpid() getpid()
+#endif
+
 /*
  * Large file (>2Gb) support using Win32 functions.
  */

+ 1 - 1
lib/curl_sha256.h

@@ -31,7 +31,7 @@
 #include <curl/curl.h>
 #include "curl_hmac.h"
 
-extern const struct HMAC_params Curl_HMAC_SHA256[1];
+extern const struct HMAC_params Curl_HMAC_SHA256;
 
 #ifndef CURL_SHA256_DIGEST_LENGTH
 #define CURL_SHA256_DIGEST_LENGTH 32 /* fixed size */

+ 1 - 1
lib/curl_sha512_256.c

@@ -34,7 +34,7 @@
  * * GnuTLS
  * * wolfSSL
  * * Schannel SSPI
- * * SecureTransport (Darwin)
+ * * Secure Transport (Darwin)
  * * mbedTLS
  * * BearSSL
  * * Rustls

+ 3 - 3
lib/curl_threads.c

@@ -103,7 +103,7 @@ int Curl_thread_join(curl_thread_t *hnd)
 #elif defined(USE_THREADS_WIN32)
 
 curl_thread_t Curl_thread_create(
-#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP)
+#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_UWP)
                                  DWORD
 #else
                                  unsigned int
@@ -111,14 +111,14 @@ curl_thread_t Curl_thread_create(
                                  (CURL_STDCALL *func) (void *),
                                  void *arg)
 {
-#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP)
+#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_UWP)
   typedef HANDLE curl_win_thread_handle_t;
 #else
   typedef uintptr_t curl_win_thread_handle_t;
 #endif
   curl_thread_t t;
   curl_win_thread_handle_t thread_handle;
-#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP)
+#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_UWP)
   thread_handle = CreateThread(NULL, 0, func, arg, 0, NULL);
 #else
   thread_handle = _beginthreadex(NULL, 0, func, arg, 0, NULL);

+ 1 - 1
lib/curl_threads.h

@@ -53,7 +53,7 @@
 #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
 
 curl_thread_t Curl_thread_create(
-#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP)
+#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_UWP)
                                  DWORD
 #else
                                  unsigned int

+ 7 - 7
lib/curl_trc.c

@@ -65,7 +65,7 @@ void Curl_debug(struct Curl_easy *data, curl_infotype type,
       "* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
     if(data->set.fdebug) {
       bool inCallback = Curl_is_in_callback(data);
-      Curl_set_in_callback(data, true);
+      Curl_set_in_callback(data, TRUE);
       (void)(*data->set.fdebug)(data, type, ptr, size, data->set.debugdata);
       Curl_set_in_callback(data, inCallback);
     }
@@ -239,7 +239,7 @@ void Curl_trc_smtp(struct Curl_easy *data, const char *fmt, ...)
 }
 #endif /* !CURL_DISABLE_SMTP */
 
-#if defined(USE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
+#if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
 struct curl_trc_feat Curl_trc_feat_ws = {
   "WS",
   CURL_LOG_LVL_NONE,
@@ -255,7 +255,7 @@ void Curl_trc_ws(struct Curl_easy *data, const char *fmt, ...)
     va_end(ap);
   }
 }
-#endif /* USE_WEBSOCKETS && !CURL_DISABLE_HTTP */
+#endif /* !CURL_DISABLE_WEBSOCKETS && !CURL_DISABLE_HTTP */
 
 #define TRC_CT_NONE        (0)
 #define TRC_CT_PROTOCOL    (1<<(0))
@@ -279,7 +279,7 @@ static struct trc_feat_def trc_feats[] = {
 #ifndef CURL_DISABLE_SMTP
   { &Curl_trc_feat_smtp,      TRC_CT_PROTOCOL },
 #endif
-#if defined(USE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
+#if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
   { &Curl_trc_feat_ws,        TRC_CT_PROTOCOL },
 #endif
 };
@@ -365,7 +365,7 @@ static CURLcode trc_opt(const char *config)
   if(!tmp)
     return CURLE_OUT_OF_MEMORY;
 
-  token = strtok_r(tmp, ", ", &tok_buf);
+  token = Curl_strtok_r(tmp, ", ", &tok_buf);
   while(token) {
     switch(*token) {
       case '-':
@@ -391,7 +391,7 @@ static CURLcode trc_opt(const char *config)
     else
       trc_apply_level_by_name(token, lvl);
 
-    token = strtok_r(NULL, ", ", &tok_buf);
+    token = Curl_strtok_r(NULL, ", ", &tok_buf);
   }
   free(tmp);
   return CURLE_OK;
@@ -399,7 +399,7 @@ static CURLcode trc_opt(const char *config)
 
 CURLcode Curl_trc_opt(const char *config)
 {
-  CURLcode result = config? trc_opt(config) : CURLE_OK;
+  CURLcode result = config ? trc_opt(config) : CURLE_OK;
 #ifdef DEBUGBUILD
   /* CURL_DEBUG can override anything */
   if(!result) {

+ 11 - 14
lib/curl_trc.h

@@ -94,11 +94,11 @@ void Curl_failf(struct Curl_easy *data,
   do { if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_smtp)) \
          Curl_trc_smtp(data, __VA_ARGS__); } while(0)
 #endif /* !CURL_DISABLE_SMTP */
-#if defined(USE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
-#define CURL_TRC_WS(data, ...) \
+#if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
+#define CURL_TRC_WS(data, ...)                             \
   do { if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_ws)) \
          Curl_trc_ws(data, __VA_ARGS__); } while(0)
-#endif /* USE_WEBSOCKETS && !CURL_DISABLE_HTTP */
+#endif /* !CURL_DISABLE_WEBSOCKETS && !CURL_DISABLE_HTTP */
 
 #else /* CURL_HAVE_C99 */
 
@@ -113,7 +113,7 @@ void Curl_failf(struct Curl_easy *data,
 #ifndef CURL_DISABLE_SMTP
 #define CURL_TRC_SMTP  Curl_trc_smtp
 #endif
-#if defined(USE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
+#if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
 #define CURL_TRC_WS    Curl_trc_ws
 #endif
 
@@ -152,8 +152,6 @@ void Curl_infof(struct Curl_easy *data,
  */
 void Curl_trc_cf_infof(struct Curl_easy *data, struct Curl_cfilter *cf,
                        const char *fmt, ...) CURL_PRINTF(3, 4);
-void Curl_trc_ft_infof(struct Curl_easy *data, struct curl_trc_feat *ft,
-                       const char *fmt, ...) CURL_PRINTF(3, 4);
 void Curl_trc_write(struct Curl_easy *data,
                     const char *fmt, ...) CURL_PRINTF(2, 3);
 void Curl_trc_read(struct Curl_easy *data,
@@ -169,7 +167,7 @@ extern struct curl_trc_feat Curl_trc_feat_smtp;
 void Curl_trc_smtp(struct Curl_easy *data,
                    const char *fmt, ...) CURL_PRINTF(2, 3);
 #endif
-#if defined(USE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
+#if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)
 extern struct curl_trc_feat Curl_trc_feat_ws;
 void Curl_trc_ws(struct Curl_easy *data,
                  const char *fmt, ...) CURL_PRINTF(2, 3);
@@ -197,13 +195,6 @@ static void Curl_trc_cf_infof(struct Curl_easy *data,
 
 struct curl_trc_feat;
 
-static void Curl_trc_ft_infof(struct Curl_easy *data,
-                              struct curl_trc_feat *ft,
-                              const char *fmt, ...)
-{
-  (void)data; (void)ft; (void)fmt;
-}
-
 static void Curl_trc_write(struct Curl_easy *data, const char *fmt, ...)
 {
   (void)data; (void)fmt;
@@ -226,6 +217,12 @@ static void Curl_trc_smtp(struct Curl_easy *data, const char *fmt, ...)
   (void)data; (void)fmt;
 }
 #endif
+#if !defined(CURL_DISABLE_WEBSOCKETS) || !defined(CURL_DISABLE_HTTP)
+static void Curl_trc_ws(struct Curl_easy *data, const char *fmt, ...)
+{
+  (void)data; (void)fmt;
+}
+#endif
 
 #endif /* !defined(CURL_DISABLE_VERBOSE_STRINGS) */
 

+ 0 - 9
lib/curlx.h

@@ -66,13 +66,4 @@
 #include "version_win32.h"
 /* "version_win32.h" provides curlx_verify_windows_version() */
 
-/* Now setup curlx_ * names for the functions that are to become curlx_ and
-   be removed from a future libcurl official API:
-   curlx_getenv
-   curlx_mprintf (and its variations)
-   curlx_strcasecompare
-   curlx_strncasecompare
-
-*/
-
 #endif /* HEADER_CURL_CURLX_H */

+ 6 - 7
lib/cw-out.c

@@ -177,8 +177,8 @@ static void cw_get_writefunc(struct Curl_easy *data, cw_out_type otype,
     *pmin_write = 0;
     break;
   case CW_OUT_HDS:
-    *pwcb = data->set.fwrite_header? data->set.fwrite_header :
-             (data->set.writeheader? data->set.fwrite_func : NULL);
+    *pwcb = data->set.fwrite_header ? data->set.fwrite_header :
+             (data->set.writeheader ? data->set.fwrite_func : NULL);
     *pwcb_data = data->set.writeheader;
     *pmax_write = 0; /* do not chunk-write headers, write them as they are */
     *pmin_write = 0;
@@ -218,12 +218,12 @@ static CURLcode cw_out_ptr_flush(struct cw_out_ctx *ctx,
   while(blen && !ctx->paused) {
     if(!flush_all && blen < min_write)
       break;
-    wlen = max_write? CURLMIN(blen, max_write) : blen;
+    wlen = max_write ? CURLMIN(blen, max_write) : blen;
     Curl_set_in_callback(data, TRUE);
     nwritten = wcb((char *)buf, 1, wlen, wcb_data);
     Curl_set_in_callback(data, FALSE);
     CURL_TRC_WRITE(data, "cw_out, wrote %zu %s bytes -> %zu",
-                   wlen, (otype == CW_OUT_BODY)? "body" : "header",
+                   wlen, (otype == CW_OUT_BODY) ? "body" : "header",
                    nwritten);
     if(CURL_WRITEFUNC_PAUSE == nwritten) {
       if(data->conn && data->conn->handler->flags & PROTOPT_NONETWORK) {
@@ -402,9 +402,8 @@ static CURLcode cw_out_write(struct Curl_easy *data,
 {
   struct cw_out_ctx *ctx = writer->ctx;
   CURLcode result;
-  bool flush_all;
+  bool flush_all = !!(type & CLIENTWRITE_EOS);
 
-  flush_all = (type & CLIENTWRITE_EOS)? TRUE:FALSE;
   if((type & CLIENTWRITE_BODY) ||
      ((type & CLIENTWRITE_HEADER) && data->set.include_header)) {
     result = cw_out_do_write(ctx, data, CW_OUT_BODY, flush_all, buf, blen);
@@ -431,7 +430,7 @@ bool Curl_cw_out_is_paused(struct Curl_easy *data)
     return FALSE;
 
   ctx = (struct cw_out_ctx *)cw_out;
-  CURL_TRC_WRITE(data, "cw-out is%spaused", ctx->paused? "" : " not");
+  CURL_TRC_WRITE(data, "cw-out is%spaused", ctx->paused ? "" : " not");
   return ctx->paused;
 }
 

+ 21 - 22
lib/doh.c

@@ -165,7 +165,7 @@ UNITTEST DOHcode doh_req_encode(const char *host,
   *dnsp++ = 0; /* append zero-length label for root */
 
   /* There are assigned TYPE codes beyond 255: use range [1..65535]  */
-  *dnsp++ = (unsigned char)(255 & (dnstype>>8)); /* upper 8 bit TYPE */
+  *dnsp++ = (unsigned char)(255 & (dnstype >> 8)); /* upper 8 bit TYPE */
   *dnsp++ = (unsigned char)(255 & dnstype);      /* lower 8 bit TYPE */
 
   *dnsp++ = '\0'; /* upper 8 bit CLASS */
@@ -180,7 +180,7 @@ UNITTEST DOHcode doh_req_encode(const char *host,
 }
 
 static size_t
-doh_write_cb(const void *contents, size_t size, size_t nmemb, void *userp)
+doh_write_cb(char *contents, size_t size, size_t nmemb, void *userp)
 {
   size_t realsize = size * nmemb;
   struct dynbuf *mem = (struct dynbuf *)userp;
@@ -198,10 +198,10 @@ static void doh_print_buf(struct Curl_easy *data,
 {
   unsigned char hexstr[LOCAL_PB_HEXMAX];
   size_t hlen = LOCAL_PB_HEXMAX;
-  bool truncated = false;
+  bool truncated = FALSE;
 
   if(len > (LOCAL_PB_HEXMAX / 2))
-    truncated = true;
+    truncated = TRUE;
   Curl_hexencode(buf, len, hexstr, hlen);
   if(!truncated)
     infof(data, "%s: len=%d, val=%s", prefix, (int)len, hexstr);
@@ -238,14 +238,14 @@ static int doh_done(struct Curl_easy *doh, CURLcode result)
   return 0;
 }
 
-#define ERROR_CHECK_SETOPT(x,y) \
-do {                                          \
-  result = curl_easy_setopt(doh, x, y);       \
-  if(result &&                                \
-     result != CURLE_NOT_BUILT_IN &&          \
-     result != CURLE_UNKNOWN_OPTION)          \
-    goto error;                               \
-} while(0)
+#define ERROR_CHECK_SETOPT(x,y)                         \
+  do {                                                  \
+    result = curl_easy_setopt((CURL *)doh, x, y);       \
+    if(result &&                                        \
+       result != CURLE_NOT_BUILT_IN &&                  \
+       result != CURLE_UNKNOWN_OPTION)                  \
+      goto error;                                       \
+  } while(0)
 
 static CURLcode doh_run_probe(struct Curl_easy *data,
                               struct doh_probe *p, DNStype dnstype,
@@ -278,7 +278,7 @@ static CURLcode doh_run_probe(struct Curl_easy *data,
 
   /* pass in the struct pointer via a local variable to please coverity and
      the gcc typecheck helpers */
-  doh->state.internal = true;
+  doh->state.internal = TRUE;
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
   doh->state.feat = &Curl_doh_trc;
 #endif
@@ -301,7 +301,7 @@ static CURLcode doh_run_probe(struct Curl_easy *data,
   ERROR_CHECK_SETOPT(CURLOPT_PROTOCOLS, CURLPROTO_HTTP|CURLPROTO_HTTPS);
 #endif
   ERROR_CHECK_SETOPT(CURLOPT_TIMEOUT_MS, (long)timeout_ms);
-  ERROR_CHECK_SETOPT(CURLOPT_SHARE, data->share);
+  ERROR_CHECK_SETOPT(CURLOPT_SHARE, (CURLSH *)data->share);
   if(data->set.err && data->set.err != stderr)
     ERROR_CHECK_SETOPT(CURLOPT_STDERR, data->set.err);
   if(Curl_trc_ft_is_verbose(data, &Curl_doh_trc))
@@ -847,15 +847,13 @@ static void doh_show(struct Curl_easy *data,
     }
     else if(a->type == DNS_TYPE_AAAA) {
       int j;
-      char buffer[128];
-      char *ptr;
-      size_t len;
-      len = msnprintf(buffer, 128, "[DoH] AAAA: ");
-      ptr = &buffer[len];
+      char buffer[128] = "[DoH] AAAA: ";
+      size_t len = strlen(buffer);
+      char *ptr = &buffer[len];
       len = sizeof(buffer) - len;
       for(j = 0; j < 16; j += 2) {
         size_t l;
-        msnprintf(ptr, len, "%s%02x%02x", j?":":"", d->addr[i].ip.v6[j],
+        msnprintf(ptr, len, "%s%02x%02x", j ? ":" : "", d->addr[i].ip.v6[j],
                   d->addr[i].ip.v6[j + 1]);
         l = strlen(ptr);
         len -= l;
@@ -1305,7 +1303,7 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data,
   if(dohp->probe[DOH_SLOT_IPV4].easy_mid < 0 &&
      dohp->probe[DOH_SLOT_IPV6].easy_mid < 0) {
     failf(data, "Could not DoH-resolve: %s", data->state.async.hostname);
-    return CONN_IS_PROXIED(data->conn)?CURLE_COULDNT_RESOLVE_PROXY:
+    return CONN_IS_PROXIED(data->conn) ? CURLE_COULDNT_RESOLVE_PROXY :
       CURLE_COULDNT_RESOLVE_HOST;
   }
   else if(!dohp->pending) {
@@ -1415,7 +1413,8 @@ void Curl_doh_close(struct Curl_easy *data)
       doh->probe[slot].easy_mid = -1;
       /* should have been called before data is removed from multi handle */
       DEBUGASSERT(data->multi);
-      probe_data = data->multi? Curl_multi_get_handle(data->multi, mid) : NULL;
+      probe_data = data->multi ? Curl_multi_get_handle(data->multi, mid) :
+        NULL;
       if(!probe_data) {
         DEBUGF(infof(data, "Curl_doh_close: xfer for mid=%"
                      FMT_OFF_T " not found!",

+ 2 - 2
lib/dynhds.c

@@ -141,7 +141,7 @@ void Curl_dynhds_set_opts(struct dynhds *dynhds, int opts)
 struct dynhds_entry *Curl_dynhds_getn(struct dynhds *dynhds, size_t n)
 {
   DEBUGASSERT(dynhds);
-  return (n < dynhds->hds_len)? dynhds->hds[n] : NULL;
+  return (n < dynhds->hds_len) ? dynhds->hds[n] : NULL;
 }
 
 struct dynhds_entry *Curl_dynhds_get(struct dynhds *dynhds, const char *name,
@@ -272,7 +272,7 @@ CURLcode Curl_dynhds_h1_add_line(struct dynhds *dynhds,
 
 CURLcode Curl_dynhds_h1_cadd_line(struct dynhds *dynhds, const char *line)
 {
-  return Curl_dynhds_h1_add_line(dynhds, line, line? strlen(line) : 0);
+  return Curl_dynhds_h1_add_line(dynhds, line, line ? strlen(line) : 0);
 }
 
 #ifdef UNITTESTS

+ 36 - 29
lib/easy.c

@@ -347,7 +347,7 @@ CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
  * curl_easy_init() is the external interface to alloc, setup and init an
  * easy handle that is returned. If anything goes wrong, NULL is returned.
  */
-struct Curl_easy *curl_easy_init(void)
+CURL *curl_easy_init(void)
 {
   CURLcode result;
   struct Curl_easy *data;
@@ -398,9 +398,9 @@ struct events {
  * Callback that gets called with a new value when the timeout should be
  * updated.
  */
-static int events_timer(struct Curl_multi *multi,    /* multi handle */
+static int events_timer(CURLM *multi,    /* multi handle */
                         long timeout_ms, /* see above */
-                        void *userp)    /* private callback pointer */
+                        void *userp)     /* private callback pointer */
 {
   struct events *ev = userp;
   (void)multi;
@@ -449,7 +449,7 @@ static short socketcb2poll(int pollmask)
  * Callback that gets called with information about socket activity to
  * monitor.
  */
-static int events_socket(struct Curl_easy *easy,      /* easy handle */
+static int events_socket(CURL *easy,      /* easy handle */
                          curl_socket_t s, /* socket */
                          int what,        /* see above */
                          void *userp,     /* private callback
@@ -461,6 +461,7 @@ static int events_socket(struct Curl_easy *easy,      /* easy handle */
   struct socketmonitor *m;
   struct socketmonitor *prev = NULL;
   bool found = FALSE;
+  struct Curl_easy *data = easy;
 
 #if defined(CURL_DISABLE_VERBOSE_STRINGS)
   (void) easy;
@@ -479,16 +480,16 @@ static int events_socket(struct Curl_easy *easy,      /* easy handle */
         else
           ev->list = nxt;
         free(m);
-        infof(easy, "socket cb: socket %" FMT_SOCKET_T " REMOVED", s);
+        infof(data, "socket cb: socket %" FMT_SOCKET_T " REMOVED", s);
       }
       else {
         /* The socket 's' is already being monitored, update the activity
            mask. Convert from libcurl bitmask to the poll one. */
         m->socket.events = socketcb2poll(what);
-        infof(easy, "socket cb: socket %" FMT_SOCKET_T
+        infof(data, "socket cb: socket %" FMT_SOCKET_T
               " UPDATED as %s%s", s,
-              (what&CURL_POLL_IN)?"IN":"",
-              (what&CURL_POLL_OUT)?"OUT":"");
+              (what&CURL_POLL_IN) ? "IN" : "",
+              (what&CURL_POLL_OUT) ? "OUT" : "");
       }
       break;
     }
@@ -499,7 +500,7 @@ static int events_socket(struct Curl_easy *easy,      /* easy handle */
   if(!found) {
     if(what == CURL_POLL_REMOVE) {
       /* should not happen if our logic is correct, but is no drama. */
-      DEBUGF(infof(easy, "socket cb: asked to REMOVE socket %"
+      DEBUGF(infof(data, "socket cb: asked to REMOVE socket %"
                    FMT_SOCKET_T "but not present!", s));
       DEBUGASSERT(0);
     }
@@ -511,9 +512,9 @@ static int events_socket(struct Curl_easy *easy,      /* easy handle */
         m->socket.events = socketcb2poll(what);
         m->socket.revents = 0;
         ev->list = m;
-        infof(easy, "socket cb: socket %" FMT_SOCKET_T " ADDED as %s%s", s,
-              (what&CURL_POLL_IN)?"IN":"",
-              (what&CURL_POLL_OUT)?"OUT":"");
+        infof(data, "socket cb: socket %" FMT_SOCKET_T " ADDED as %s%s", s,
+              (what&CURL_POLL_IN) ? "IN" : "",
+              (what&CURL_POLL_OUT) ? "OUT" : "");
       }
       else
         return CURLE_OUT_OF_MEMORY;
@@ -617,7 +618,7 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
       DEBUGASSERT(data);
 
       /* loop over the monitored sockets to see which ones had activity */
-      for(i = 0; i< numfds; i++) {
+      for(i = 0; i < numfds; i++) {
         if(fds[i].revents) {
           /* socket activity, tell libcurl */
           int act = poll2cselect(fds[i].revents); /* convert */
@@ -809,7 +810,7 @@ static CURLcode easy_perform(struct Curl_easy *data, bool events)
  * curl_easy_perform() is the external interface that performs a blocking
  * transfer as previously setup.
  */
-CURLcode curl_easy_perform(struct Curl_easy *data)
+CURLcode curl_easy_perform(CURL *data)
 {
   return easy_perform(data, FALSE);
 }
@@ -830,8 +831,9 @@ CURLcode curl_easy_perform_ev(struct Curl_easy *data)
  * curl_easy_cleanup() is the external interface to cleaning/freeing the given
  * easy handle.
  */
-void curl_easy_cleanup(struct Curl_easy *data)
+void curl_easy_cleanup(CURL *ptr)
 {
+  struct Curl_easy *data = ptr;
   if(GOOD_EASY_HANDLE(data)) {
     SIGPIPE_VARIABLE(pipe_st);
     sigpipe_ignore(data, &pipe_st);
@@ -845,7 +847,7 @@ void curl_easy_cleanup(struct Curl_easy *data)
  * information from a performed transfer and similar.
  */
 #undef curl_easy_getinfo
-CURLcode curl_easy_getinfo(struct Curl_easy *data, CURLINFO info, ...)
+CURLcode curl_easy_getinfo(CURL *data, CURLINFO info, ...)
 {
   va_list arg;
   void *paramp;
@@ -877,7 +879,7 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src)
   memset(dst->set.blobs, 0, BLOB_LAST * sizeof(struct curl_blob *));
 
   /* duplicate all strings */
-  for(i = (enum dupstring)0; i< STRING_LASTZEROTERMINATED; i++) {
+  for(i = (enum dupstring)0; i < STRING_LASTZEROTERMINATED; i++) {
     result = Curl_setstropt(&dst->set.str[i], src->set.str[i]);
     if(result)
       return result;
@@ -919,8 +921,9 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src)
  * given input easy handle. The returned handle will be a new working handle
  * with all options set exactly as the input source handle.
  */
-struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
+CURL *curl_easy_duphandle(CURL *d)
 {
+  struct Curl_easy *data = d;
   struct Curl_easy *outcurl = calloc(1, sizeof(struct Curl_easy));
   if(!outcurl)
     goto fail;
@@ -937,6 +940,7 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
     goto fail;
 
   Curl_dyn_init(&outcurl->state.headerb, CURL_MAX_HTTP_HEADER);
+  Curl_netrc_init(&outcurl->state.netrc);
 
   /* the connection pool is setup on demand */
   outcurl->state.lastconnect_id = -1;
@@ -1066,8 +1070,9 @@ fail:
  * curl_easy_reset() is an external interface that allows an app to re-
  * initialize a session handle to the default values.
  */
-void curl_easy_reset(struct Curl_easy *data)
+void curl_easy_reset(CURL *d)
 {
+  struct Curl_easy *data = d;
   Curl_req_hard_reset(&data->req, data);
 
   /* zero out UserDefined data: */
@@ -1107,7 +1112,7 @@ void curl_easy_reset(struct Curl_easy *data)
  * NOTE: This is one of few API functions that are allowed to be called from
  * within a callback.
  */
-CURLcode curl_easy_pause(struct Curl_easy *data, int action)
+CURLcode curl_easy_pause(CURL *d, int action)
 {
   struct SingleRequest *k;
   CURLcode result = CURLE_OK;
@@ -1115,6 +1120,7 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
   int newstate;
   bool recursive = FALSE;
   bool keep_changed, unpause_read, not_all_paused;
+  struct Curl_easy *data = d;
 
   if(!GOOD_EASY_HANDLE(data) || !data->conn)
     /* crazy input, do not continue */
@@ -1127,8 +1133,8 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
 
   /* first switch off both pause bits then set the new pause bits */
   newstate = (k->keepon &~ (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE)) |
-    ((action & CURLPAUSE_RECV)?KEEP_RECV_PAUSE:0) |
-    ((action & CURLPAUSE_SEND)?KEEP_SEND_PAUSE:0);
+    ((action & CURLPAUSE_RECV) ? KEEP_RECV_PAUSE : 0) |
+    ((action & CURLPAUSE_SEND) ? KEEP_SEND_PAUSE : 0);
 
   keep_changed = ((newstate & (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE)) != oldstate);
   not_all_paused = (newstate & (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) !=
@@ -1218,12 +1224,12 @@ static CURLcode easy_connection(struct Curl_easy *data,
  * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
  * Returns CURLE_OK on success, error code on error.
  */
-CURLcode curl_easy_recv(struct Curl_easy *data, void *buffer, size_t buflen,
-                        size_t *n)
+CURLcode curl_easy_recv(CURL *d, void *buffer, size_t buflen, size_t *n)
 {
   CURLcode result;
   ssize_t n1;
   struct connectdata *c;
+  struct Curl_easy *data = d;
 
   if(Curl_is_in_callback(data))
     return CURLE_RECURSIVE_API_CALL;
@@ -1247,7 +1253,7 @@ CURLcode curl_easy_recv(struct Curl_easy *data, void *buffer, size_t buflen,
   return CURLE_OK;
 }
 
-#ifdef USE_WEBSOCKETS
+#ifndef CURL_DISABLE_WEBSOCKETS
 CURLcode Curl_connect_only_attach(struct Curl_easy *data)
 {
   CURLcode result;
@@ -1264,7 +1270,7 @@ CURLcode Curl_connect_only_attach(struct Curl_easy *data)
 
   return CURLE_OK;
 }
-#endif /* USE_WEBSOCKETS */
+#endif /* !CURL_DISABLE_WEBSOCKETS */
 
 /*
  * Sends data over the connected socket.
@@ -1301,11 +1307,11 @@ CURLcode Curl_senddata(struct Curl_easy *data, const void *buffer,
  * Sends data over the connected socket. Use after successful
  * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
  */
-CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,
-                        size_t buflen, size_t *n)
+CURLcode curl_easy_send(CURL *d, const void *buffer, size_t buflen, size_t *n)
 {
   size_t written = 0;
   CURLcode result;
+  struct Curl_easy *data = d;
   if(Curl_is_in_callback(data))
     return CURLE_RECURSIVE_API_CALL;
 
@@ -1317,8 +1323,9 @@ CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,
 /*
  * Performs connection upkeep for the given session handle.
  */
-CURLcode curl_easy_upkeep(struct Curl_easy *data)
+CURLcode curl_easy_upkeep(CURL *d)
 {
+  struct Curl_easy *data = d;
   /* Verify that we got an easy handle we can work with. */
   if(!GOOD_EASY_HANDLE(data))
     return CURLE_BAD_FUNCTION_ARGUMENT;

+ 1 - 1
lib/easyif.h

@@ -30,7 +30,7 @@
 CURLcode Curl_senddata(struct Curl_easy *data, const void *buffer,
                        size_t buflen, size_t *n);
 
-#ifdef USE_WEBSOCKETS
+#ifndef CURL_DISABLE_WEBSOCKETS
 CURLcode Curl_connect_only_attach(struct Curl_easy *data);
 #endif
 

+ 8 - 6
lib/escape.c

@@ -29,6 +29,8 @@
 
 #include <curl/curl.h>
 
+struct Curl_easy;
+
 #include "urldata.h"
 #include "warnless.h"
 #include "escape.h"
@@ -53,7 +55,7 @@ char *curl_unescape(const char *string, int length)
 /* Escapes for URL the given unescaped string of given length.
  * 'data' is ignored since 7.82.0.
  */
-char *curl_easy_escape(struct Curl_easy *data, const char *string,
+char *curl_easy_escape(CURL *data, const char *string,
                        int inlength)
 {
   size_t length;
@@ -63,7 +65,7 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string,
   if(!string || (inlength < 0))
     return NULL;
 
-  length = (inlength?(size_t)inlength:strlen(string));
+  length = (inlength ? (size_t)inlength : strlen(string));
   if(!length)
     return strdup("");
 
@@ -82,7 +84,7 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string,
       /* encode it */
       const char hex[] = "0123456789ABCDEF";
       char out[3]={'%'};
-      out[1] = hex[in>>4];
+      out[1] = hex[in >> 4];
       out[2] = hex[in & 0xf];
       if(Curl_dyn_addn(&d, out, 3))
         return NULL;
@@ -128,7 +130,7 @@ CURLcode Curl_urldecode(const char *string, size_t length,
   DEBUGASSERT(string);
   DEBUGASSERT(ctrl >= REJECT_NADA); /* crash on TRUE/FALSE */
 
-  alloc = (length?length:strlen(string));
+  alloc = (length ? length : strlen(string));
   ns = malloc(alloc + 1);
 
   if(!ns)
@@ -176,7 +178,7 @@ CURLcode Curl_urldecode(const char *string, size_t length,
  * If olen == NULL, no output length is stored.
  * 'data' is ignored since 7.82.0.
  */
-char *curl_easy_unescape(struct Curl_easy *data, const char *string,
+char *curl_easy_unescape(CURL *data, const char *string,
                          int length, int *olen)
 {
   char *str = NULL;
@@ -223,7 +225,7 @@ void Curl_hexencode(const unsigned char *src, size_t len, /* input length */
     while(len-- && (olen >= 3)) {
       /* clang-tidy warns on this line without this comment: */
       /* NOLINTNEXTLINE(clang-analyzer-core.UndefinedBinaryOperatorResult) */
-      *out++ = (unsigned char)hex[(*src & 0xF0)>>4];
+      *out++ = (unsigned char)hex[(*src & 0xF0) >> 4];
       *out++ = (unsigned char)hex[*src & 0x0F];
       ++src;
       olen -= 2;

+ 1 - 1
lib/file.c

@@ -489,7 +489,7 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
     headerlen =
       msnprintf(header, sizeof(header),
                 "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
-                Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
+                Curl_wkday[tm->tm_wday ? tm->tm_wday-1 : 6],
                 tm->tm_mday,
                 Curl_month[tm->tm_mon],
                 tm->tm_year + 1900,

+ 26 - 22
lib/formdata.c

@@ -26,6 +26,8 @@
 
 #include <curl/curl.h>
 
+struct Curl_easy;
+
 #include "formdata.h"
 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_FORM_API)
 
@@ -282,8 +284,8 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
       if(current_form->name)
         return_value = CURL_FORMADD_OPTION_TWICE;
       else {
-        char *name = array_state?
-          array_value:va_arg(params, char *);
+        char *name = array_state ?
+          array_value : va_arg(params, char *);
         if(name)
           current_form->name = name; /* store for the moment */
         else
@@ -295,7 +297,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
         return_value = CURL_FORMADD_OPTION_TWICE;
       else
         current_form->namelength =
-          array_state?(size_t)array_value:(size_t)va_arg(params, long);
+          array_state ? (size_t)array_value : (size_t)va_arg(params, long);
       break;
 
       /*
@@ -309,7 +311,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
         return_value = CURL_FORMADD_OPTION_TWICE;
       else {
         char *value =
-          array_state?array_value:va_arg(params, char *);
+          array_state ? array_value : va_arg(params, char *);
         if(value)
           current_form->value = value; /* store for the moment */
         else
@@ -318,13 +320,14 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
       break;
     case CURLFORM_CONTENTSLENGTH:
       current_form->contentslength =
-        array_state?(size_t)array_value:(size_t)va_arg(params, long);
+        array_state ? (size_t)array_value : (size_t)va_arg(params, long);
       break;
 
     case CURLFORM_CONTENTLEN:
       current_form->flags |= CURL_HTTPPOST_LARGE;
       current_form->contentslength =
-        array_state?(curl_off_t)(size_t)array_value:va_arg(params, curl_off_t);
+        array_state ? (curl_off_t)(size_t)array_value :
+        va_arg(params, curl_off_t);
       break;
 
       /* Get contents from a given filename */
@@ -332,8 +335,8 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
       if(current_form->flags & (HTTPPOST_PTRCONTENTS|HTTPPOST_READFILE))
         return_value = CURL_FORMADD_OPTION_TWICE;
       else {
-        const char *filename = array_state?
-          array_value:va_arg(params, char *);
+        const char *filename = array_state ?
+          array_value : va_arg(params, char *);
         if(filename) {
           current_form->value = strdup(filename);
           if(!current_form->value)
@@ -351,7 +354,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
       /* We upload a file */
     case CURLFORM_FILE:
       {
-        const char *filename = array_state?array_value:
+        const char *filename = array_state ? array_value :
           va_arg(params, char *);
 
         if(current_form->value) {
@@ -401,7 +404,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
         return_value = CURL_FORMADD_OPTION_TWICE;
       else {
         char *buffer =
-          array_state?array_value:va_arg(params, char *);
+          array_state ? array_value : va_arg(params, char *);
         if(buffer) {
           current_form->buffer = buffer; /* store for the moment */
           current_form->value = buffer; /* make it non-NULL to be accepted
@@ -417,7 +420,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
         return_value = CURL_FORMADD_OPTION_TWICE;
       else
         current_form->bufferlength =
-          array_state?(size_t)array_value:(size_t)va_arg(params, long);
+          array_state ? (size_t)array_value : (size_t)va_arg(params, long);
       break;
 
     case CURLFORM_STREAM:
@@ -426,7 +429,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
         return_value = CURL_FORMADD_OPTION_TWICE;
       else {
         char *userp =
-          array_state?array_value:va_arg(params, char *);
+          array_state ? array_value : va_arg(params, char *);
         if(userp) {
           current_form->userp = userp;
           current_form->value = userp; /* this is not strictly true but we
@@ -442,7 +445,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
     case CURLFORM_CONTENTTYPE:
       {
         const char *contenttype =
-          array_state?array_value:va_arg(params, char *);
+          array_state ? array_value : va_arg(params, char *);
         if(current_form->contenttype) {
           if(current_form->flags & HTTPPOST_FILENAME) {
             if(contenttype) {
@@ -485,8 +488,8 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
       {
         /* this "cast increases required alignment of target type" but
            we consider it OK anyway */
-        struct curl_slist *list = array_state?
-          (struct curl_slist *)(void *)array_value:
+        struct curl_slist *list = array_state ?
+          (struct curl_slist *)(void *)array_value :
           va_arg(params, struct curl_slist *);
 
         if(current_form->contentheader)
@@ -499,7 +502,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
     case CURLFORM_FILENAME:
     case CURLFORM_BUFFER:
       {
-        const char *filename = array_state?array_value:
+        const char *filename = array_state ? array_value :
           va_arg(params, char *);
         if(current_form->showfilename)
           return_value = CURL_FORMADD_OPTION_TWICE;
@@ -569,7 +572,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
       if(((form->flags & HTTPPOST_FILENAME) ||
           (form->flags & HTTPPOST_BUFFER)) &&
          !form->contenttype) {
-        char *f = (form->flags & HTTPPOST_BUFFER)?
+        char *f = (form->flags & HTTPPOST_BUFFER) ?
           form->showfilename : form->value;
         char const *type;
         type = Curl_mime_contenttype(f);
@@ -603,8 +606,8 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
            app passed in a bad combo, so we better check for that first. */
         if(form->name) {
           /* copy name (without strdup; possibly not null-terminated) */
-          form->name = Curl_memdup0(form->name, form->namelength?
-                                    form->namelength:
+          form->name = Curl_memdup0(form->name, form->namelength ?
+                                    form->namelength :
                                     strlen(form->name));
         }
         if(!form->name) {
@@ -790,7 +793,7 @@ static CURLcode setname(curl_mimepart *part, const char *name, size_t len)
 /* wrap call to fseeko so it matches the calling convention of callback */
 static int fseeko_wrapper(void *stream, curl_off_t offset, int whence)
 {
-#if defined(HAVE__FSEEKI64)
+#if defined(_WIN32) && defined(USE_WIN32_LARGE_FILES)
   return _fseeki64(stream, (__int64)offset, whence);
 #elif defined(HAVE_FSEEKO) && defined(HAVE_DECL_FSEEKO)
   return fseeko(stream, (off_t)offset, whence);
@@ -811,7 +814,7 @@ static int fseeko_wrapper(void *stream, curl_off_t offset, int whence)
  * a NULL pointer in the 'data' argument.
  */
 
-CURLcode Curl_getformdata(struct Curl_easy *data,
+CURLcode Curl_getformdata(CURL *data,
                           curl_mimepart *finalform,
                           struct curl_httppost *post,
                           curl_read_callback fread_func)
@@ -896,7 +899,8 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
         }
         else if(post->flags & HTTPPOST_BUFFER)
           result = curl_mime_data(part, post->buffer,
-                                  post->bufferlength? post->bufferlength: -1);
+                                  post->bufferlength ?
+                                  post->bufferlength : -1);
         else if(post->flags & HTTPPOST_CALLBACK) {
           /* the contents should be read with the callback and the size is set
              with the contentslength */

+ 1 - 1
lib/formdata.h

@@ -49,7 +49,7 @@ struct FormInfo {
   bool showfilename_alloc;
 };
 
-CURLcode Curl_getformdata(struct Curl_easy *data,
+CURLcode Curl_getformdata(CURL *data,
                           curl_mimepart *,
                           struct curl_httppost *post,
                           curl_read_callback fread_func);

+ 129 - 293
lib/ftp.c

@@ -302,10 +302,10 @@ static void close_secondarysocket(struct Curl_easy *data)
  * requests on files respond with headers passed to the client/stdout that
  * looked like HTTP ones.
  *
- * This approach is not very elegant, it causes confusion and is error-prone.
- * It is subject for removal at the next (or at least a future) soname bump.
- * Until then you can test the effects of the removal by undefining the
- * following define named CURL_FTP_HTTPSTYLE_HEAD.
+ * This approach is not elegant, it causes confusion and is error-prone. It is
+ * subject for removal at the next (or at least a future) soname bump. Until
+ * then you can test the effects of the removal by undefining the following
+ * define named CURL_FTP_HTTPSTYLE_HEAD.
  */
 #define CURL_FTP_HTTPSTYLE_HEAD 1
 
@@ -419,138 +419,19 @@ static const struct Curl_cwtype ftp_cw_lc = {
 #endif /* CURL_PREFER_LF_LINEENDS */
 /***********************************************************************
  *
- * AcceptServerConnect()
- *
- * After connection request is received from the server this function is
- * called to accept the connection and close the listening socket
- *
- */
-static CURLcode AcceptServerConnect(struct Curl_easy *data)
-{
-  struct connectdata *conn = data->conn;
-  curl_socket_t sock = conn->sock[SECONDARYSOCKET];
-  curl_socket_t s = CURL_SOCKET_BAD;
-#ifdef USE_IPV6
-  struct Curl_sockaddr_storage add;
-#else
-  struct sockaddr_in add;
-#endif
-  curl_socklen_t size = (curl_socklen_t) sizeof(add);
-  CURLcode result;
-
-  if(0 == getsockname(sock, (struct sockaddr *) &add, &size)) {
-    size = sizeof(add);
-
-    s = accept(sock, (struct sockaddr *) &add, &size);
-  }
-
-  if(CURL_SOCKET_BAD == s) {
-    failf(data, "Error accept()ing server connect");
-    return CURLE_FTP_PORT_FAILED;
-  }
-  infof(data, "Connection accepted from server");
-  /* when this happens within the DO state it is important that we mark us as
-     not needing DO_MORE anymore */
-  conn->bits.do_more = FALSE;
-
-  (void)curlx_nonblock(s, TRUE); /* enable non-blocking */
-  /* Replace any filter on SECONDARY with one listening on this socket */
-  result = Curl_conn_tcp_accepted_set(data, conn, SECONDARYSOCKET, &s);
-  if(result) {
-    sclose(s);
-    return result;
-  }
-
-  if(data->set.fsockopt) {
-    int error = 0;
-
-    /* activate callback for setting socket options */
-    Curl_set_in_callback(data, true);
-    error = data->set.fsockopt(data->set.sockopt_client,
-                               s,
-                               CURLSOCKTYPE_ACCEPT);
-    Curl_set_in_callback(data, false);
-
-    if(error) {
-      close_secondarysocket(data);
-      return CURLE_ABORTED_BY_CALLBACK;
-    }
-  }
-
-  return CURLE_OK;
-
-}
-
-/*
- * ftp_timeleft_accept() returns the amount of milliseconds left allowed for
- * waiting server to connect. If the value is negative, the timeout time has
- * already elapsed.
- *
- * The start time is stored in progress.t_acceptdata - as set with
- * Curl_pgrsTime(..., TIMER_STARTACCEPT);
- *
- */
-static timediff_t ftp_timeleft_accept(struct Curl_easy *data)
-{
-  timediff_t timeout_ms = DEFAULT_ACCEPT_TIMEOUT;
-  timediff_t other;
-  struct curltime now;
-
-  if(data->set.accepttimeout > 0)
-    timeout_ms = data->set.accepttimeout;
-
-  now = Curl_now();
-
-  /* check if the generic timeout possibly is set shorter */
-  other = Curl_timeleft(data, &now, FALSE);
-  if(other && (other < timeout_ms))
-    /* note that this also works fine for when other happens to be negative
-       due to it already having elapsed */
-    timeout_ms = other;
-  else {
-    /* subtract elapsed time */
-    timeout_ms -= Curl_timediff(now, data->progress.t_acceptdata);
-    if(!timeout_ms)
-      /* avoid returning 0 as that means no timeout! */
-      return -1;
-  }
-
-  return timeout_ms;
-}
-
-
-/***********************************************************************
- *
- * ReceivedServerConnect()
- *
- * After allowing server to connect to us from data port, this function
- * checks both data connection for connection establishment and ctrl
- * connection for a negative response regarding a failure in connecting
+ * ftp_check_ctrl_on_data_wait()
  *
  */
-static CURLcode ReceivedServerConnect(struct Curl_easy *data, bool *received)
+static CURLcode ftp_check_ctrl_on_data_wait(struct Curl_easy *data)
 {
   struct connectdata *conn = data->conn;
   curl_socket_t ctrl_sock = conn->sock[FIRSTSOCKET];
-  curl_socket_t data_sock = conn->sock[SECONDARYSOCKET];
   struct ftp_conn *ftpc = &conn->proto.ftpc;
   struct pingpong *pp = &ftpc->pp;
-  int socketstate = 0;
-  timediff_t timeout_ms;
   ssize_t nread;
   int ftpcode;
   bool response = FALSE;
 
-  *received = FALSE;
-
-  timeout_ms = ftp_timeleft_accept(data);
-  infof(data, "Checking for server connect");
-  if(timeout_ms < 0) {
-    /* if a timeout was already reached, bail out */
-    failf(data, "Accept timeout occurred while waiting server connect");
-    return CURLE_FTP_ACCEPT_TIMEOUT;
-  }
-
   /* First check whether there is a cached response from server */
   if(Curl_dyn_len(&pp->recvbuf) && (*Curl_dyn_ptr(&pp->recvbuf) > '3')) {
     /* Data connection could not be established, let's return */
@@ -562,26 +443,22 @@ static CURLcode ReceivedServerConnect(struct Curl_easy *data, bool *received)
   if(pp->overflow)
     /* there is pending control data still in the buffer to read */
     response = TRUE;
-  else
-    socketstate = Curl_socket_check(ctrl_sock, data_sock, CURL_SOCKET_BAD, 0);
-
-  /* see if the connection request is already here */
-  switch(socketstate) {
-  case -1: /* error */
-    /* let's die here */
-    failf(data, "Error while waiting for server connect");
-    return CURLE_FTP_ACCEPT_FAILED;
-  case 0:  /* Server connect is not received yet */
-    break; /* loop */
-  default:
-    if(socketstate & CURL_CSELECT_IN2) {
-      infof(data, "Ready to accept data connection from server");
-      *received = TRUE;
+  else {
+    int socketstate = Curl_socket_check(ctrl_sock, CURL_SOCKET_BAD,
+                                        CURL_SOCKET_BAD, 0);
+    /* see if the connection request is already here */
+    switch(socketstate) {
+    case -1: /* error */
+      /* let's die here */
+      failf(data, "Error while waiting for server connect");
+      return CURLE_FTP_ACCEPT_FAILED;
+    default:
+      if(socketstate & CURL_CSELECT_IN)
+        response = TRUE;
+      break;
     }
-    else if(socketstate & CURL_CSELECT_IN)
-      response = TRUE;
-    break;
   }
+
   if(response) {
     infof(data, "Ctrl conn has data while waiting for data conn");
     if(pp->overflow > 3) {
@@ -600,7 +477,6 @@ static CURLcode ReceivedServerConnect(struct Curl_easy *data, bool *received)
              noticed. Leave the 226 in there and use this as a trigger to read
              the data socket. */
           infof(data, "Got 226 before data activity");
-          *received = TRUE;
           return CURLE_OK;
         }
       }
@@ -619,7 +495,6 @@ static CURLcode ReceivedServerConnect(struct Curl_easy *data, bool *received)
   return CURLE_OK;
 }
 
-
 /***********************************************************************
  *
  * InitiateTransfer()
@@ -635,12 +510,6 @@ static CURLcode InitiateTransfer(struct Curl_easy *data)
   bool connected;
 
   CURL_TRC_FTP(data, "InitiateTransfer()");
-  if(conn->bits.ftp_use_data_ssl && data->set.ftp_use_port &&
-     !Curl_conn_is_ssl(conn, SECONDARYSOCKET)) {
-    result = Curl_ssl_cfilter_add(data, conn, SECONDARYSOCKET);
-    if(result)
-      return result;
-  }
   result = Curl_conn_connect(data, SECONDARYSOCKET, TRUE, &connected);
   if(result || !connected)
     return result;
@@ -653,12 +522,14 @@ static CURLcode InitiateTransfer(struct Curl_easy *data)
     /* set the SO_SNDBUF for the secondary socket for those who need it */
     Curl_sndbuf_init(conn->sock[SECONDARYSOCKET]);
 
-    Curl_xfer_setup2(data, CURL_XFER_SEND, -1, TRUE);
+    /* FTP upload, shutdown DATA, ignore shutdown errors, as we rely
+     * on the server response on the CONTROL connection. */
+    Curl_xfer_setup2(data, CURL_XFER_SEND, -1, TRUE, TRUE);
   }
   else {
-    /* FTP download: */
+    /* FTP download, shutdown, do not ignore errors */
     Curl_xfer_setup2(data, CURL_XFER_RECV,
-                     conn->proto.ftpc.retr_size_saved, TRUE);
+                     conn->proto.ftpc.retr_size_saved, TRUE, FALSE);
   }
 
   conn->proto.ftpc.pp.pending_resp = TRUE; /* expect server response */
@@ -667,60 +538,6 @@ static CURLcode InitiateTransfer(struct Curl_easy *data)
   return CURLE_OK;
 }
 
-/***********************************************************************
- *
- * AllowServerConnect()
- *
- * When we have issue the PORT command, we have told the server to connect to
- * us. This function checks whether data connection is established if so it is
- * accepted.
- *
- */
-static CURLcode AllowServerConnect(struct Curl_easy *data, bool *connected)
-{
-  timediff_t timeout_ms;
-  CURLcode result = CURLE_OK;
-
-  *connected = FALSE;
-  infof(data, "Preparing for accepting server on data port");
-
-  /* Save the time we start accepting server connect */
-  Curl_pgrsTime(data, TIMER_STARTACCEPT);
-
-  timeout_ms = ftp_timeleft_accept(data);
-  if(timeout_ms < 0) {
-    /* if a timeout was already reached, bail out */
-    failf(data, "Accept timeout occurred while waiting server connect");
-    result = CURLE_FTP_ACCEPT_TIMEOUT;
-    goto out;
-  }
-
-  /* see if the connection request is already here */
-  result = ReceivedServerConnect(data, connected);
-  if(result)
-    goto out;
-
-  if(*connected) {
-    result = AcceptServerConnect(data);
-    if(result)
-      goto out;
-
-    result = InitiateTransfer(data);
-    if(result)
-      goto out;
-  }
-  else {
-    /* Add timeout to multi handle and break out of the loop */
-    Curl_expire(data, data->set.accepttimeout ?
-                data->set.accepttimeout: DEFAULT_ACCEPT_TIMEOUT,
-                EXPIRE_FTP_ACCEPT);
-  }
-
-out:
-  CURL_TRC_FTP(data, "AllowServerConnect() -> %d", result);
-  return result;
-}
-
 static bool ftp_endofresp(struct Curl_easy *data, struct connectdata *conn,
                           char *line, size_t len, int *code)
 {
@@ -864,8 +681,8 @@ CURLcode Curl_GetFTPResponse(struct Curl_easy *data,
        */
     }
     else if(!Curl_conn_data_pending(data, FIRSTSOCKET)) {
-      curl_socket_t wsock = Curl_pp_needs_flush(data, pp)?
-                            sockfd : CURL_SOCKET_BAD;
+      curl_socket_t wsock = Curl_pp_needs_flush(data, pp) ?
+        sockfd : CURL_SOCKET_BAD;
       int ev = Curl_socket_check(sockfd, CURL_SOCKET_BAD, wsock, interval_ms);
       if(ev < 0) {
         failf(data, "FTP response aborted due to select/poll error: %d",
@@ -914,7 +731,7 @@ static CURLcode ftp_state_user(struct Curl_easy *data,
 {
   CURLcode result = Curl_pp_sendf(data,
                                   &conn->proto.ftpc.pp, "USER %s",
-                                  conn->user?conn->user:"");
+                                  conn->user ? conn->user : "");
   if(!result) {
     struct ftp_conn *ftpc = &conn->proto.ftpc;
     ftpc->ftp_trying_alternative = FALSE;
@@ -1138,7 +955,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
       /* attempt to get the address of the given interface name */
       switch(Curl_if2ip(conn->remote_addr->family,
 #ifdef USE_IPV6
-                        Curl_ipv6_scope(&conn->remote_addr->sa_addr),
+                        Curl_ipv6_scope(&conn->remote_addr->curl_sa_addr),
                         conn->scope_id,
 #endif
                         ipstr, hbuf, sizeof(hbuf))) {
@@ -1304,12 +1121,6 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
     conn->bits.ftp_use_eprt = TRUE;
 #endif
 
-  /* Replace any filter on SECONDARY with one listening on this socket */
-  result = Curl_conn_tcp_listen_set(data, conn, SECONDARYSOCKET, &portsock);
-  if(result)
-    goto out;
-  portsock = CURL_SOCKET_BAD; /* now held in filter */
-
   for(; fcmd != DONE; fcmd++) {
 
     if(!conn->bits.ftp_use_eprt && (EPRT == fcmd))
@@ -1343,7 +1154,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
        */
 
       result = Curl_pp_sendf(data, &ftpc->pp, "%s |%d|%s|%hu|", mode[fcmd],
-                             sa->sa_family == AF_INET?1:2,
+                             sa->sa_family == AF_INET ? 1 : 2,
                              myhost, port);
       if(result) {
         failf(data, "Failure sending EPRT command: %s",
@@ -1368,7 +1179,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
         source++;
       }
       *dest = 0;
-      msnprintf(dest, 20, ",%d,%d", (int)(port>>8), (int)(port&0xff));
+      msnprintf(dest, 20, ",%d,%d", (int)(port >> 8), (int)(port & 0xff));
 
       result = Curl_pp_sendf(data, &ftpc->pp, "%s %s", mode[fcmd], target);
       if(result) {
@@ -1382,9 +1193,13 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
 
   /* store which command was sent */
   ftpc->count1 = fcmd;
-
   ftp_state(data, FTP_PORT);
 
+  /* Replace any filter on SECONDARY with one listening on this socket */
+  result = Curl_conn_tcp_listen_set(data, conn, SECONDARYSOCKET, &portsock);
+  if(!result)
+    portsock = CURL_SOCKET_BAD; /* now held in filter */
+
 out:
   /* If we looked up a dns_entry, now is the time to safely release it */
   if(dns_entry)
@@ -1392,6 +1207,18 @@ out:
   if(result) {
     ftp_state(data, FTP_STOP);
   }
+  else {
+    /* successfully setup the list socket filter. Do we need more? */
+    if(conn->bits.ftp_use_data_ssl && data->set.ftp_use_port &&
+       !Curl_conn_is_ssl(conn, SECONDARYSOCKET)) {
+      result = Curl_ssl_cfilter_add(data, conn, SECONDARYSOCKET);
+    }
+    data->conn->bits.do_more = FALSE;
+    Curl_pgrsTime(data, TIMER_STARTACCEPT);
+    Curl_expire(data, data->set.accepttimeout ?
+                data->set.accepttimeout: DEFAULT_ACCEPT_TIMEOUT,
+                EXPIRE_FTP_ACCEPT);
+  }
   if(portsock != CURL_SOCKET_BAD)
     Curl_socket_close(data, conn, portsock);
   return result;
@@ -1426,7 +1253,7 @@ static CURLcode ftp_state_use_pasv(struct Curl_easy *data,
     conn->bits.ftp_use_epsv = TRUE;
 #endif
 
-  modeoff = conn->bits.ftp_use_epsv?0:1;
+  modeoff = conn->bits.ftp_use_epsv ? 0 : 1;
 
   result = Curl_pp_sendf(data, &ftpc->pp, "%s", mode[modeoff]);
   if(!result) {
@@ -1469,9 +1296,9 @@ static CURLcode ftp_state_prepare_transfer(struct Curl_easy *data)
       struct ftp_conn *ftpc = &conn->proto.ftpc;
       if(!conn->proto.ftpc.file)
         result = Curl_pp_sendf(data, &ftpc->pp, "PRET %s",
-                               data->set.str[STRING_CUSTOMREQUEST]?
-                               data->set.str[STRING_CUSTOMREQUEST]:
-                               (data->state.list_only?"NLST":"LIST"));
+                               data->set.str[STRING_CUSTOMREQUEST] ?
+                               data->set.str[STRING_CUSTOMREQUEST] :
+                               (data->state.list_only ? "NLST" : "LIST"));
       else if(data->state.upload)
         result = Curl_pp_sendf(data, &ftpc->pp, "PRET STOR %s",
                                conn->proto.ftpc.file);
@@ -1576,11 +1403,11 @@ static CURLcode ftp_state_list(struct Curl_easy *data)
   }
 
   cmd = aprintf("%s%s%s",
-                data->set.str[STRING_CUSTOMREQUEST]?
-                data->set.str[STRING_CUSTOMREQUEST]:
-                (data->state.list_only?"NLST":"LIST"),
-                lstArg? " ": "",
-                lstArg? lstArg: "");
+                data->set.str[STRING_CUSTOMREQUEST] ?
+                data->set.str[STRING_CUSTOMREQUEST] :
+                (data->state.list_only ? "NLST" : "LIST"),
+                lstArg ? " " : "",
+                lstArg ? lstArg : "");
   free(lstArg);
 
   if(!cmd)
@@ -1702,10 +1529,10 @@ static CURLcode ftp_state_ul_setup(struct Curl_easy *data,
 
     /* Let's read off the proper amount of bytes from the input. */
     if(data->set.seek_func) {
-      Curl_set_in_callback(data, true);
+      Curl_set_in_callback(data, TRUE);
       seekerr = data->set.seek_func(data->set.seek_client,
                                     data->state.resume_from, SEEK_SET);
-      Curl_set_in_callback(data, false);
+      Curl_set_in_callback(data, FALSE);
     }
 
     if(seekerr != CURL_SEEKFUNC_OK) {
@@ -1736,7 +1563,7 @@ static CURLcode ftp_state_ul_setup(struct Curl_easy *data,
       } while(passed < data->state.resume_from);
     }
     /* now, decrease the size of the read */
-    if(data->state.infilesize>0) {
+    if(data->state.infilesize > 0) {
       data->state.infilesize -= data->state.resume_from;
 
       if(data->state.infilesize <= 0) {
@@ -1756,7 +1583,7 @@ static CURLcode ftp_state_ul_setup(struct Curl_easy *data,
     /* we have passed, proceed as normal */
   } /* resume_from */
 
-  result = Curl_pp_sendf(data, &ftpc->pp, append?"APPE %s":"STOR %s",
+  result = Curl_pp_sendf(data, &ftpc->pp, append ? "APPE %s" : "STOR %s",
                          ftpc->file);
   if(!result)
     ftp_state(data, FTP_STOR);
@@ -1804,7 +1631,7 @@ static CURLcode ftp_state_quote(struct Curl_easy *data,
     int i = 0;
 
     /* Skip count1 items in the linked list */
-    while((i< ftpc->count1) && item) {
+    while((i < ftpc->count1) && item) {
       item = item->next;
       i++;
     }
@@ -2038,7 +1865,7 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data,
     if(!ftpc->newhost)
       return CURLE_OUT_OF_MEMORY;
 
-    ftpc->newport = (unsigned short)(((ip[4]<<8) + ip[5]) & 0xffff);
+    ftpc->newport = (unsigned short)(((ip[4] << 8) + ip[5]) & 0xffff);
   }
   else if(ftpc->count1 == 0) {
     /* EPSV failed, move on to PASV */
@@ -2101,7 +1928,7 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data,
   }
 
   result = Curl_conn_setup(data, conn, SECONDARYSOCKET, addr,
-                           conn->bits.ftp_use_data_ssl?
+                           conn->bits.ftp_use_data_ssl ?
                            CURL_CF_SSL_ENABLE : CURL_CF_SSL_DISABLE);
 
   if(result) {
@@ -2215,10 +2042,10 @@ static CURLcode client_write_header(struct Curl_easy *data,
    * headers from CONNECT should not automatically be part of the
    * output. */
   CURLcode result;
-  int save = data->set.include_header;
+  bool save = data->set.include_header;
   data->set.include_header = TRUE;
   result = Curl_client_write(data, CLIENTWRITE_HEADER, buf, blen);
-  data->set.include_header = save? TRUE:FALSE;
+  data->set.include_header = save;
   return result;
 }
 
@@ -2267,15 +2094,16 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
           return result;
 
         /* format: "Tue, 15 Nov 1994 12:45:26" */
-        headerbuflen = msnprintf(headerbuf, sizeof(headerbuf),
-                  "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
-                  Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
-                  tm->tm_mday,
-                  Curl_month[tm->tm_mon],
-                  tm->tm_year + 1900,
-                  tm->tm_hour,
-                  tm->tm_min,
-                  tm->tm_sec);
+        headerbuflen =
+          msnprintf(headerbuf, sizeof(headerbuf),
+                    "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
+                    Curl_wkday[tm->tm_wday ? tm->tm_wday-1 : 6],
+                    tm->tm_mday,
+                    Curl_month[tm->tm_mon],
+                    tm->tm_year + 1900,
+                    tm->tm_hour,
+                    tm->tm_min,
+                    tm->tm_sec);
         result = client_write_header(data, headerbuf, headerbuflen);
         if(result)
           return result;
@@ -2387,7 +2215,7 @@ static CURLcode ftp_state_retr(struct Curl_easy *data,
     else {
       /* We got a file size report, so we check that there actually is a
          part of the file left to get, or else we go home.  */
-      if(data->state.resume_from< 0) {
+      if(data->state.resume_from < 0) {
         /* We are supposed to download the last abs(from) bytes */
         if(filesize < -data->state.resume_from) {
           failf(data, "Offset (%" FMT_OFF_T
@@ -2562,21 +2390,21 @@ static CURLcode ftp_state_stor_resp(struct Curl_easy *data,
 
   /* PORT means we are now awaiting the server to connect to us. */
   if(data->set.ftp_use_port) {
+    struct ftp_conn *ftpc = &conn->proto.ftpc;
     bool connected;
 
     ftp_state(data, FTP_STOP); /* no longer in STOR state */
 
-    result = AllowServerConnect(data, &connected);
+    result = Curl_conn_connect(data, SECONDARYSOCKET, FALSE, &connected);
     if(result)
       return result;
 
     if(!connected) {
-      struct ftp_conn *ftpc = &conn->proto.ftpc;
       infof(data, "Data conn was not available immediately");
       ftpc->wait_data_conn = TRUE;
+      return ftp_check_ctrl_on_data_wait(data);
     }
-
-    return CURLE_OK;
+    ftpc->wait_data_conn = FALSE;
   }
   return InitiateTransfer(data);
 }
@@ -2626,10 +2454,10 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data,
        !data->set.ignorecl &&
        (ftp->downloadsize < 1)) {
       /*
-       * It seems directory listings either do not show the size or very
-       * often uses size 0 anyway. ASCII transfers may very well turn out
-       * that the transferred amount of data is not the same as this line
-       * tells, why using this number in those cases only confuses us.
+       * It seems directory listings either do not show the size or often uses
+       * size 0 anyway. ASCII transfers may cause that the transferred amount
+       * of data is not the same as this line tells, why using this number in
+       * those cases only confuses us.
        *
        * Example D above makes this parsing a little tricky */
       char *bytes;
@@ -2676,21 +2504,22 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data,
     conn->proto.ftpc.retr_size_saved = size;
 
     if(data->set.ftp_use_port) {
+      struct ftp_conn *ftpc = &conn->proto.ftpc;
       bool connected;
 
-      result = AllowServerConnect(data, &connected);
+      result = Curl_conn_connect(data, SECONDARYSOCKET, FALSE, &connected);
       if(result)
         return result;
 
       if(!connected) {
-        struct ftp_conn *ftpc = &conn->proto.ftpc;
         infof(data, "Data conn was not available immediately");
         ftp_state(data, FTP_STOP);
         ftpc->wait_data_conn = TRUE;
+        return ftp_check_ctrl_on_data_wait(data);
       }
+      ftpc->wait_data_conn = FALSE;
     }
-    else
-      return InitiateTransfer(data);
+    return InitiateTransfer(data);
   }
   else {
     if((instate == FTP_LIST) && (ftpcode == 450)) {
@@ -2700,8 +2529,8 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data,
     }
     else {
       failf(data, "RETR response: %03d", ftpcode);
-      return instate == FTP_RETR && ftpcode == 550?
-        CURLE_REMOTE_FILE_NOT_FOUND:
+      return instate == FTP_RETR && ftpcode == 550 ?
+        CURLE_REMOTE_FILE_NOT_FOUND :
         CURLE_FTP_COULDNT_RETR_FILE;
     }
   }
@@ -2753,7 +2582,7 @@ static CURLcode ftp_state_user_resp(struct Curl_easy *data,
     /* 331 Password required for ...
        (the server requires to send the user's password too) */
     result = Curl_pp_sendf(data, &ftpc->pp, "PASS %s",
-                           conn->passwd?conn->passwd:"");
+                           conn->passwd ? conn->passwd : "");
     if(!result)
       ftp_state(data, FTP_PASS);
   }
@@ -2964,7 +2793,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
       if(ftpcode/100 == 2)
         /* We have enabled SSL for the data connection! */
         conn->bits.ftp_use_data_ssl =
-          (data->set.use_ssl != CURLUSESSL_CONTROL) ? TRUE : FALSE;
+          (data->set.use_ssl != CURLUSESSL_CONTROL);
       /* FTP servers typically responds with 500 if they decide to reject
          our 'P' request */
       else if(data->set.use_ssl > CURLUSESSL_CONTROL)
@@ -3281,7 +3110,7 @@ static CURLcode ftp_multi_statemach(struct Curl_easy *data,
   /* Check for the state outside of the Curl_socket_check() return code checks
      since at times we are in fact already in this state when this function
      gets called. */
-  *done = (ftpc->state == FTP_STOP) ? TRUE : FALSE;
+  *done = (ftpc->state == FTP_STOP);
 
   return result;
 }
@@ -3403,9 +3232,9 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status,
 
   if(data->state.wildcardmatch) {
     if(data->set.chunk_end && ftpc->file) {
-      Curl_set_in_callback(data, true);
+      Curl_set_in_callback(data, TRUE);
       data->set.chunk_end(data->set.wildcardptr);
-      Curl_set_in_callback(data, false);
+      Curl_set_in_callback(data, FALSE);
     }
     ftpc->known_filesize = -1;
   }
@@ -3432,7 +3261,8 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status,
         if(data->set.ftp_filemethod == FTPFILE_NOCWD)
           pathLen = 0; /* relative path => working directory is FTP home */
         else
-          pathLen -= ftpc->file?strlen(ftpc->file):0; /* file is url-decoded */
+          /* file is url-decoded */
+          pathLen -= ftpc->file ? strlen(ftpc->file) : 0;
 
         rawPath[pathLen] = '\0';
         ftpc->prevpath = rawPath;
@@ -3550,7 +3380,7 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status,
     }
     else if(!ftpc->dont_check &&
             !data->req.bytecount &&
-            (data->req.size>0)) {
+            (data->req.size > 0)) {
       failf(data, "No data was received");
       result = CURLE_FTP_COULDNT_RETR_FILE;
     }
@@ -3634,7 +3464,7 @@ CURLcode ftp_sendquote(struct Curl_easy *data,
 static int ftp_need_type(struct connectdata *conn,
                          bool ascii_wanted)
 {
-  return conn->proto.ftpc.transfertype != (ascii_wanted?'A':'I');
+  return conn->proto.ftpc.transfertype != (ascii_wanted ? 'A' : 'I');
 }
 
 /***********************************************************************
@@ -3651,7 +3481,7 @@ static CURLcode ftp_nb_type(struct Curl_easy *data,
 {
   struct ftp_conn *ftpc = &conn->proto.ftpc;
   CURLcode result;
-  char want = (char)(ascii?'A':'I');
+  char want = (char)(ascii ? 'A' : 'I');
 
   if(ftpc->transfertype == want) {
     ftp_state(data, newstate);
@@ -3714,20 +3544,25 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
    * complete */
   struct FTP *ftp = NULL;
 
-  /* if the second connection is not done yet, wait for it to have
-   * connected to the remote host. When using proxy tunneling, this
-   * means the tunnel needs to have been establish. However, we
-   * can not expect the remote host to talk to us in any way yet.
-   * So, when using ftps: the SSL handshake will not start until we
-   * tell the remote server that we are there. */
+  /* if the second connection has been set up, try to connect it fully
+   * to the remote host. This may not complete at this time, for several
+   * reasons:
+   * - we do EPTR and the server will not connect to our listen socket
+   *   until we send more FTP commands
+   * - an SSL filter is in place and the server will not start the TLS
+   *   handshake until we send more FTP commands
+   */
   if(conn->cfilter[SECONDARYSOCKET]) {
+    bool is_eptr = Curl_conn_is_tcp_listen(data, SECONDARYSOCKET);
     result = Curl_conn_connect(data, SECONDARYSOCKET, FALSE, &connected);
-    if(result || !Curl_conn_is_ip_connected(data, SECONDARYSOCKET)) {
-      if(result && (ftpc->count1 == 0)) {
+    if(result || (!connected && !is_eptr &&
+                  !Curl_conn_is_ip_connected(data, SECONDARYSOCKET))) {
+      if(result && !is_eptr && (ftpc->count1 == 0)) {
         *completep = -1; /* go back to DOING please */
         /* this is a EPSV connect failing, try PASV instead */
         return ftp_epsv_disable(data, conn);
       }
+      *completep = (int)complete;
       return result;
     }
   }
@@ -3760,16 +3595,14 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
     if(ftpc->wait_data_conn) {
       bool serv_conned;
 
-      result = ReceivedServerConnect(data, &serv_conned);
+      result = Curl_conn_connect(data, SECONDARYSOCKET, TRUE, &serv_conned);
       if(result)
         return result; /* Failed to accept data connection */
 
       if(serv_conned) {
         /* It looks data connection is established */
-        result = AcceptServerConnect(data);
         ftpc->wait_data_conn = FALSE;
-        if(!result)
-          result = InitiateTransfer(data);
+        result = InitiateTransfer(data);
 
         if(result)
           return result;
@@ -3777,6 +3610,11 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
         *completep = 1; /* this state is now complete when the server has
                            connected back to us */
       }
+      else {
+        result = ftp_check_ctrl_on_data_wait(data);
+        if(result)
+          return result;
+      }
     }
     else if(data->state.upload) {
       result = ftp_nb_type(data, conn, data->state.prefer_ascii,
@@ -3912,8 +3750,7 @@ static CURLcode init_wc_data(struct Curl_easy *data)
     last_slash++;
     if(last_slash[0] == '\0') {
       wildcard->state = CURLWC_CLEAN;
-      result = ftp_parse_url_path(data);
-      return result;
+      return ftp_parse_url_path(data);
     }
     wildcard->pattern = strdup(last_slash);
     if(!wildcard->pattern)
@@ -3929,8 +3766,7 @@ static CURLcode init_wc_data(struct Curl_easy *data)
     }
     else { /* only list */
       wildcard->state = CURLWC_CLEAN;
-      result = ftp_parse_url_path(data);
-      return result;
+      return ftp_parse_url_path(data);
     }
   }
 
@@ -4050,11 +3886,11 @@ static CURLcode wc_statemach(struct Curl_easy *data)
       infof(data, "Wildcard - START of \"%s\"", finfo->filename);
       if(data->set.chunk_bgn) {
         long userresponse;
-        Curl_set_in_callback(data, true);
+        Curl_set_in_callback(data, TRUE);
         userresponse = data->set.chunk_bgn(
           finfo, data->set.wildcardptr,
           (int)Curl_llist_count(&wildcard->filelist));
-        Curl_set_in_callback(data, false);
+        Curl_set_in_callback(data, FALSE);
         switch(userresponse) {
         case CURL_CHUNK_BGN_FUNC_SKIP:
           infof(data, "Wildcard - \"%s\" skipped by user",
@@ -4093,9 +3929,9 @@ static CURLcode wc_statemach(struct Curl_easy *data)
 
     case CURLWC_SKIP: {
       if(data->set.chunk_end) {
-        Curl_set_in_callback(data, true);
+        Curl_set_in_callback(data, TRUE);
         data->set.chunk_end(data->set.wildcardptr);
-        Curl_set_in_callback(data, false);
+        Curl_set_in_callback(data, FALSE);
       }
       Curl_node_remove(Curl_llist_head(&wildcard->filelist));
       wildcard->state = (Curl_llist_count(&wildcard->filelist) == 0) ?
@@ -4406,7 +4242,7 @@ CURLcode ftp_parse_url_path(struct Curl_easy *data)
       if(data->set.ftp_filemethod == FTPFILE_NOCWD)
         n = 0; /* CWD to entry for relative paths */
       else
-        n -= ftpc->file?strlen(ftpc->file):0;
+        n -= ftpc->file ? strlen(ftpc->file) : 0;
 
       if((strlen(oldPath) == n) && !strncmp(rawPath, oldPath, n)) {
         infof(data, "Request has same path as previous transfer");

+ 2 - 2
lib/ftplistparser.c

@@ -334,7 +334,7 @@ static CURLcode ftp_pl_insert_finfo(struct Curl_easy *data,
     compare = Curl_fnmatch;
 
   /* filter pattern-corresponding filenames */
-  Curl_set_in_callback(data, true);
+  Curl_set_in_callback(data, TRUE);
   if(compare(data->set.fnmatch_data, wc->pattern,
              finfo->filename) == 0) {
     /* discard symlink which is containing multiple " -> " */
@@ -346,7 +346,7 @@ static CURLcode ftp_pl_insert_finfo(struct Curl_easy *data,
   else {
     add = FALSE;
   }
-  Curl_set_in_callback(data, false);
+  Curl_set_in_callback(data, FALSE);
 
   if(add) {
     Curl_llist_append(llist, finfo, &infop->list);

+ 2 - 2
lib/getenv.c

@@ -31,7 +31,7 @@
 
 static char *GetEnv(const char *variable)
 {
-#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP) || \
+#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_UWP) || \
   defined(__ORBIS__) || defined(__PROSPERO__) /* PlayStation 4 and 5 */
   (void)variable;
   return NULL;
@@ -70,7 +70,7 @@ static char *GetEnv(const char *variable)
   }
 #else
   char *env = getenv(variable);
-  return (env && env[0])?strdup(env):NULL;
+  return (env && env[0]) ? strdup(env) : NULL;
 #endif
 }
 

+ 14 - 11
lib/getinfo.c

@@ -57,7 +57,7 @@ CURLcode Curl_initinfo(struct Curl_easy *data)
   pro->t_starttransfer = 0;
   pro->timespent = 0;
   pro->t_redirect = 0;
-  pro->is_t_startransfer_set = false;
+  pro->is_t_startransfer_set = FALSE;
 
   info->httpcode = 0;
   info->httpproxycode = 0;
@@ -96,7 +96,7 @@ static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info,
 {
   switch(info) {
   case CURLINFO_EFFECTIVE_URL:
-    *param_charp = data->state.url?data->state.url:(char *)"";
+    *param_charp = data->state.url ? data->state.url : (char *)"";
     break;
   case CURLINFO_EFFECTIVE_METHOD: {
     const char *m = data->set.str[STRING_CUSTOMREQUEST];
@@ -405,12 +405,12 @@ static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
     *param_offt = data->progress.ul.speed;
     break;
   case CURLINFO_CONTENT_LENGTH_DOWNLOAD_T:
-    *param_offt = (data->progress.flags & PGRS_DL_SIZE_KNOWN)?
-      data->progress.dl.total_size:-1;
+    *param_offt = (data->progress.flags & PGRS_DL_SIZE_KNOWN) ?
+      data->progress.dl.total_size : -1;
     break;
   case CURLINFO_CONTENT_LENGTH_UPLOAD_T:
-    *param_offt = (data->progress.flags & PGRS_UL_SIZE_KNOWN)?
-      data->progress.ul.total_size:-1;
+    *param_offt = (data->progress.flags & PGRS_UL_SIZE_KNOWN) ?
+      data->progress.ul.total_size : -1;
     break;
    case CURLINFO_TOTAL_TIME_T:
     *param_offt = data->progress.timespent;
@@ -446,9 +446,12 @@ static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
     *param_offt = data->id;
     break;
   case CURLINFO_CONN_ID:
-    *param_offt = data->conn?
+    *param_offt = data->conn ?
       data->conn->connection_id : data->state.recent_conn_id;
     break;
+  case CURLINFO_EARLYDATA_SENT_T:
+    *param_offt = data->progress.earlydata_sent;
+    break;
   default:
     return CURLE_UNKNOWN_OPTION;
   }
@@ -512,12 +515,12 @@ static CURLcode getinfo_double(struct Curl_easy *data, CURLINFO info,
     *param_doublep = (double)data->progress.ul.speed;
     break;
   case CURLINFO_CONTENT_LENGTH_DOWNLOAD:
-    *param_doublep = (data->progress.flags & PGRS_DL_SIZE_KNOWN)?
-      (double)data->progress.dl.total_size:-1;
+    *param_doublep = (data->progress.flags & PGRS_DL_SIZE_KNOWN) ?
+      (double)data->progress.dl.total_size : -1;
     break;
   case CURLINFO_CONTENT_LENGTH_UPLOAD:
-    *param_doublep = (data->progress.flags & PGRS_UL_SIZE_KNOWN)?
-      (double)data->progress.ul.total_size:-1;
+    *param_doublep = (data->progress.flags & PGRS_UL_SIZE_KNOWN) ?
+      (double)data->progress.ul.total_size : -1;
     break;
   case CURLINFO_REDIRECT_TIME:
     *param_doublep = DOUBLE_SECS(data->progress.t_redirect);

+ 1 - 1
lib/headers.c

@@ -54,7 +54,7 @@ static void copy_header_external(struct Curl_header_store *hs,
      impossible for applications to do == comparisons, as that would otherwise
      be very tempting and then lead to the reserved bits not being reserved
      anymore. */
-  h->origin = (unsigned int)(hs->type | (1<<27));
+  h->origin = (unsigned int)(hs->type | (1 << 27));
   h->anchor = e;
 }
 

+ 32 - 38
lib/hmac.c

@@ -49,8 +49,6 @@
 static const unsigned char hmac_ipad = 0x36;
 static const unsigned char hmac_opad = 0x5C;
 
-
-
 struct HMAC_context *
 Curl_HMAC_init(const struct HMAC_params *hashparams,
                const unsigned char *key,
@@ -62,42 +60,40 @@ Curl_HMAC_init(const struct HMAC_params *hashparams,
   unsigned char b;
 
   /* Create HMAC context. */
-  i = sizeof(*ctxt) + 2 * hashparams->hmac_ctxtsize +
-    hashparams->hmac_resultlen;
+  i = sizeof(*ctxt) + 2 * hashparams->ctxtsize + hashparams->resultlen;
   ctxt = malloc(i);
 
   if(!ctxt)
     return ctxt;
 
-  ctxt->hmac_hash = hashparams;
-  ctxt->hmac_hashctxt1 = (void *) (ctxt + 1);
-  ctxt->hmac_hashctxt2 = (void *) ((char *) ctxt->hmac_hashctxt1 +
-      hashparams->hmac_ctxtsize);
+  ctxt->hash = hashparams;
+  ctxt->hashctxt1 = (void *) (ctxt + 1);
+  ctxt->hashctxt2 = (void *) ((char *) ctxt->hashctxt1 + hashparams->ctxtsize);
 
   /* If the key is too long, replace it by its hash digest. */
-  if(keylen > hashparams->hmac_maxkeylen) {
-    (*hashparams->hmac_hinit)(ctxt->hmac_hashctxt1);
-    (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, key, keylen);
-    hkey = (unsigned char *) ctxt->hmac_hashctxt2 + hashparams->hmac_ctxtsize;
-    (*hashparams->hmac_hfinal)(hkey, ctxt->hmac_hashctxt1);
+  if(keylen > hashparams->maxkeylen) {
+    hashparams->hinit(ctxt->hashctxt1);
+    hashparams->hupdate(ctxt->hashctxt1, key, keylen);
+    hkey = (unsigned char *) ctxt->hashctxt2 + hashparams->ctxtsize;
+    hashparams->hfinal(hkey, ctxt->hashctxt1);
     key = hkey;
-    keylen = hashparams->hmac_resultlen;
+    keylen = hashparams->resultlen;
   }
 
   /* Prime the two hash contexts with the modified key. */
-  (*hashparams->hmac_hinit)(ctxt->hmac_hashctxt1);
-  (*hashparams->hmac_hinit)(ctxt->hmac_hashctxt2);
+  hashparams->hinit(ctxt->hashctxt1);
+  hashparams->hinit(ctxt->hashctxt2);
 
   for(i = 0; i < keylen; i++) {
     b = (unsigned char)(*key ^ hmac_ipad);
-    (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, &b, 1);
+    hashparams->hupdate(ctxt->hashctxt1, &b, 1);
     b = (unsigned char)(*key++ ^ hmac_opad);
-    (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2, &b, 1);
+    hashparams->hupdate(ctxt->hashctxt2, &b, 1);
   }
 
-  for(; i < hashparams->hmac_maxkeylen; i++) {
-    (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, &hmac_ipad, 1);
-    (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2, &hmac_opad, 1);
+  for(; i < hashparams->maxkeylen; i++) {
+    hashparams->hupdate(ctxt->hashctxt1, &hmac_ipad, 1);
+    hashparams->hupdate(ctxt->hashctxt2, &hmac_opad, 1);
   }
 
   /* Done, return pointer to HMAC context. */
@@ -105,31 +101,29 @@ Curl_HMAC_init(const struct HMAC_params *hashparams,
 }
 
 int Curl_HMAC_update(struct HMAC_context *ctxt,
-                     const unsigned char *data,
+                     const unsigned char *ptr,
                      unsigned int len)
 {
   /* Update first hash calculation. */
-  (*ctxt->hmac_hash->hmac_hupdate)(ctxt->hmac_hashctxt1, data, len);
+  ctxt->hash->hupdate(ctxt->hashctxt1, ptr, len);
   return 0;
 }
 
 
-int Curl_HMAC_final(struct HMAC_context *ctxt, unsigned char *result)
+int Curl_HMAC_final(struct HMAC_context *ctxt, unsigned char *output)
 {
-  const struct HMAC_params *hashparams = ctxt->hmac_hash;
+  const struct HMAC_params *hashparams = ctxt->hash;
 
-  /* Do not get result if called with a null parameter: only release
+  /* Do not get output if called with a null parameter: only release
      storage. */
 
-  if(!result)
-    result = (unsigned char *) ctxt->hmac_hashctxt2 +
-     ctxt->hmac_hash->hmac_ctxtsize;
+  if(!output)
+    output = (unsigned char *) ctxt->hashctxt2 + ctxt->hash->ctxtsize;
 
-  (*hashparams->hmac_hfinal)(result, ctxt->hmac_hashctxt1);
-  (*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2,
-   result, hashparams->hmac_resultlen);
-  (*hashparams->hmac_hfinal)(result, ctxt->hmac_hashctxt2);
-  free((char *) ctxt);
+  hashparams->hfinal(output, ctxt->hashctxt1);
+  hashparams->hupdate(ctxt->hashctxt2, output, hashparams->resultlen);
+  hashparams->hfinal(output, ctxt->hashctxt2);
+  free(ctxt);
   return 0;
 }
 
@@ -144,15 +138,15 @@ int Curl_HMAC_final(struct HMAC_context *ctxt, unsigned char *result)
  * hashparams [in]     - The hash function (Curl_HMAC_MD5).
  * key        [in]     - The key to use.
  * keylen     [in]     - The length of the key.
- * data       [in]     - The data to encrypt.
- * datalen    [in]     - The length of the data.
+ * buf        [in]     - The data to encrypt.
+ * buflen     [in]     - The length of the data.
  * output     [in/out] - The output buffer.
  *
  * Returns CURLE_OK on success.
  */
 CURLcode Curl_hmacit(const struct HMAC_params *hashparams,
                      const unsigned char *key, const size_t keylen,
-                     const unsigned char *data, const size_t datalen,
+                     const unsigned char *buf, const size_t buflen,
                      unsigned char *output)
 {
   struct HMAC_context *ctxt =
@@ -162,7 +156,7 @@ CURLcode Curl_hmacit(const struct HMAC_params *hashparams,
     return CURLE_OUT_OF_MEMORY;
 
   /* Update the digest with the given challenge */
-  Curl_HMAC_update(ctxt, data, curlx_uztoui(datalen));
+  Curl_HMAC_update(ctxt, buf, curlx_uztoui(buflen));
 
   /* Finalise the digest */
   Curl_HMAC_final(ctxt, output);

+ 13 - 11
lib/hostip.c

@@ -313,7 +313,7 @@ static struct Curl_dns_entry *fetch_addr(struct Curl_easy *data,
   /* See if the returned entry matches the required resolve mode */
   if(dns && data->conn->ip_version != CURL_IPRESOLVE_WHATEVER) {
     int pf = PF_INET;
-    bool found = false;
+    bool found = FALSE;
     struct Curl_addrinfo *addr = dns->addr;
 
 #ifdef PF_INET6
@@ -323,7 +323,7 @@ static struct Curl_dns_entry *fetch_addr(struct Curl_easy *data,
 
     while(addr) {
       if(addr->ai_family == pf) {
-        found = true;
+        found = TRUE;
         break;
       }
       addr = addr->ai_next;
@@ -630,7 +630,7 @@ bool Curl_ipv6works(struct Curl_easy *data)
       ipv6_works = 1;
       sclose(s);
     }
-    return (ipv6_works>0)?TRUE:FALSE;
+    return (ipv6_works > 0);
   }
 }
 #endif /* USE_IPV6 */
@@ -739,7 +739,7 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
     /* notify the resolver start callback */
     if(data->set.resolver_start) {
       int st;
-      Curl_set_in_callback(data, true);
+      Curl_set_in_callback(data, TRUE);
       st = data->set.resolver_start(
 #ifdef USE_CURL_ASYNC
         data->state.async.resolver,
@@ -748,7 +748,7 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
 #endif
         NULL,
         data->set.resolver_start_client);
-      Curl_set_in_callback(data, false);
+      Curl_set_in_callback(data, FALSE);
       if(st)
         return CURLRESOLV_ERROR;
     }
@@ -798,7 +798,9 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
         return CURLRESOLV_ERROR;
 
       if(strcasecompare(hostname, "localhost") ||
-         tailmatch(hostname, ".localhost"))
+         strcasecompare(hostname, "localhost.") ||
+         tailmatch(hostname, ".localhost") ||
+         tailmatch(hostname, ".localhost."))
         addr = get_localhost(port, hostname);
 #ifndef CURL_DISABLE_DOH
       else if(allowDOH && data->set.doh && !ipnum)
@@ -1068,7 +1070,7 @@ void Curl_resolv_unlink(struct Curl_easy *data, struct Curl_dns_entry **pdns)
 static void hostcache_unlink_entry(void *entry)
 {
   struct Curl_dns_entry *dns = (struct Curl_dns_entry *) entry;
-  DEBUGASSERT(dns && (dns->refcount>0));
+  DEBUGASSERT(dns && (dns->refcount > 0));
 
   dns->refcount--;
   if(dns->refcount == 0) {
@@ -1129,7 +1131,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
   char *host_end;
 
   /* Default is no wildcard found */
-  data->state.wildcard_resolve = false;
+  data->state.wildcard_resolve = FALSE;
 
   for(hostp = data->state.resolve; hostp; hostp = hostp->next) {
     char entry_id[MAX_HOSTCACHE_LEN];
@@ -1179,7 +1181,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
       char *end_ptr;
       bool permanent = TRUE;
       unsigned long tmp_port;
-      bool error = true;
+      bool error = TRUE;
       char *host_begin = hostp->data;
       size_t hlen = 0;
 
@@ -1256,7 +1258,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
       if(!head)
         goto err;
 
-      error = false;
+      error = FALSE;
 err:
       if(error) {
         failf(data, "Couldn't parse CURLOPT_RESOLVE entry '%s'",
@@ -1316,7 +1318,7 @@ err:
       /* Wildcard hostname */
       if((hlen == 1) && (host_begin[0] == '*')) {
         infof(data, "RESOLVE *:%d using wildcard", port);
-        data->state.wildcard_resolve = true;
+        data->state.wildcard_resolve = TRUE;
       }
     }
   }

+ 4 - 0
lib/hostip4.c

@@ -126,8 +126,10 @@ struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
   int res;
 #endif
   struct Curl_addrinfo *ai = NULL;
+#if !(defined(HAVE_GETADDRINFO) && defined(HAVE_GETADDRINFO_THREADSAFE))
   struct hostent *h = NULL;
   struct hostent *buf = NULL;
+#endif
 
 #if defined(HAVE_GETADDRINFO) && defined(HAVE_GETADDRINFO_THREADSAFE)
   struct addrinfo hints;
@@ -288,12 +290,14 @@ struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
 #endif /* (HAVE_GETADDRINFO && HAVE_GETADDRINFO_THREADSAFE) ||
            HAVE_GETHOSTBYNAME_R */
 
+#if !(defined(HAVE_GETADDRINFO) && defined(HAVE_GETADDRINFO_THREADSAFE))
   if(h) {
     ai = Curl_he2ai(h, port);
 
     if(buf) /* used a *_r() function */
       free(buf);
   }
+#endif
 
   return ai;
 }

+ 23 - 16
lib/hsts.c

@@ -159,7 +159,7 @@ CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname,
   do {
     while(*p && ISBLANK(*p))
       p++;
-    if(strncasecompare("max-age=", p, 8)) {
+    if(strncasecompare("max-age", p, 7)) {
       bool quoted = FALSE;
       CURLofft offt;
       char *endp;
@@ -167,9 +167,14 @@ CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname,
       if(gotma)
         return CURLE_BAD_FUNCTION_ARGUMENT;
 
-      p += 8;
+      p += 7;
       while(*p && ISBLANK(*p))
         p++;
+      if(*p++ != '=')
+        return CURLE_BAD_FUNCTION_ARGUMENT;
+      while(*p && ISBLANK(*p))
+        p++;
+
       if(*p == '\"') {
         p++;
         quoted = TRUE;
@@ -249,24 +254,23 @@ CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname,
 struct stsentry *Curl_hsts(struct hsts *h, const char *hostname,
                            bool subdomain)
 {
+  struct stsentry *bestsub = NULL;
   if(h) {
-    char buffer[MAX_HSTS_HOSTLEN + 1];
     time_t now = time(NULL);
     size_t hlen = strlen(hostname);
     struct Curl_llist_node *e;
     struct Curl_llist_node *n;
+    size_t blen = 0;
 
     if((hlen > MAX_HSTS_HOSTLEN) || !hlen)
       return NULL;
-    memcpy(buffer, hostname, hlen);
     if(hostname[hlen-1] == '.')
       /* remove the trailing dot */
       --hlen;
-    buffer[hlen] = 0;
-    hostname = buffer;
 
     for(e = Curl_llist_head(&h->list); e; e = n) {
       struct stsentry *sts = Curl_node_elem(e);
+      size_t ntail;
       n = Curl_node_next(e);
       if(sts->expires <= now) {
         /* remove expired entries */
@@ -274,20 +278,23 @@ struct stsentry *Curl_hsts(struct hsts *h, const char *hostname,
         hsts_free(sts);
         continue;
       }
-      if(subdomain && sts->includeSubDomains) {
-        size_t ntail = strlen(sts->host);
-        if(ntail < hlen) {
-          size_t offs = hlen - ntail;
-          if((hostname[offs-1] == '.') &&
-             strncasecompare(&hostname[offs], sts->host, ntail))
-            return sts;
+      ntail = strlen(sts->host);
+      if((subdomain && sts->includeSubDomains) && (ntail < hlen)) {
+        size_t offs = hlen - ntail;
+        if((hostname[offs-1] == '.') &&
+           strncasecompare(&hostname[offs], sts->host, ntail) &&
+           (ntail > blen)) {
+          /* save the tail match with the longest tail */
+          bestsub = sts;
+          blen = ntail;
         }
       }
-      if(strcasecompare(hostname, sts->host))
+      /* avoid strcasecompare because the host name is not null terminated */
+      if((hlen == ntail) && strncasecompare(hostname, sts->host, hlen))
         return sts;
     }
   }
-  return NULL; /* no match */
+  return bestsub;
 }
 
 /*
@@ -439,7 +446,7 @@ static CURLcode hsts_add(struct hsts *h, char *line)
     e = Curl_hsts(h, p, subdomain);
     if(!e)
       result = hsts_create(h, p, subdomain, expires);
-    else {
+    else if(strcasecompare(p, e->host)) {
       /* the same hostname, use the largest expire time */
       if(expires > e->expires)
         e->expires = expires;

+ 84 - 243
lib/http.c

@@ -407,7 +407,7 @@ static CURLcode http_perhapsrewind(struct Curl_easy *data,
 {
   curl_off_t bytessent = data->req.writebytecount;
   curl_off_t expectsend = Curl_creader_total_length(data);
-  curl_off_t upload_remain = (expectsend >= 0)? (expectsend - bytessent) : -1;
+  curl_off_t upload_remain = (expectsend >= 0) ? (expectsend - bytessent) : -1;
   bool little_upload_remains = (upload_remain >= 0 && upload_remain < 2000);
   bool needs_rewind = Curl_creader_needs_rewind(data);
   /* By default, we would like to abort the transfer when little or unknown
@@ -463,14 +463,14 @@ static CURLcode http_perhapsrewind(struct Curl_easy *data,
   if(abort_upload) {
     if(upload_remain >= 0)
       infof(data, "%s%sclose instead of sending %" FMT_OFF_T " more bytes",
-            ongoing_auth? ongoing_auth : "",
-            ongoing_auth? " send, " : "",
+            ongoing_auth ? ongoing_auth : "",
+            ongoing_auth ? " send, " : "",
             upload_remain);
     else
       infof(data, "%s%sclose instead of sending unknown amount "
             "of more bytes",
-            ongoing_auth? ongoing_auth : "",
-            ongoing_auth? " send, " : "");
+            ongoing_auth ? ongoing_auth : "",
+            ongoing_auth ? " send, " : "");
     /* We decided to abort the ongoing transfer */
     streamclose(conn, "Mid-auth HTTP and much data left to send");
     /* FIXME: questionable manipulation here, can we do this differently? */
@@ -502,7 +502,7 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data)
     return CURLE_OK;
 
   if(data->state.authproblem)
-    return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK;
+    return data->set.http_fail_on_error ? CURLE_HTTP_RETURNED_ERROR : CURLE_OK;
 
   if((data->state.aptr.user || data->set.str[STRING_BEARER]) &&
      ((data->req.httpcode == 401) ||
@@ -677,7 +677,7 @@ output_auth_headers(struct Curl_easy *data,
           auth, data->state.aptr.user ?
           data->state.aptr.user : "");
 #endif
-    authstatus->multipass = (!authstatus->done) ? TRUE : FALSE;
+    authstatus->multipass = !authstatus->done;
   }
   else
     authstatus->multipass = FALSE;
@@ -1229,163 +1229,6 @@ static const char *get_http_string(const struct Curl_easy *data,
 }
 #endif
 
-enum proxy_use {
-  HEADER_SERVER,  /* direct to server */
-  HEADER_PROXY,   /* regular request to proxy */
-  HEADER_CONNECT  /* sending CONNECT to a proxy */
-};
-
-static bool hd_name_eq(const char *n1, size_t n1len,
-                       const char *n2, size_t n2len)
-{
-  if(n1len == n2len) {
-    return strncasecompare(n1, n2, n1len);
-  }
-  return FALSE;
-}
-
-CURLcode Curl_dynhds_add_custom(struct Curl_easy *data,
-                                bool is_connect,
-                                struct dynhds *hds)
-{
-  struct connectdata *conn = data->conn;
-  char *ptr;
-  struct curl_slist *h[2];
-  struct curl_slist *headers;
-  int numlists = 1; /* by default */
-  int i;
-
-#ifndef CURL_DISABLE_PROXY
-  enum proxy_use proxy;
-
-  if(is_connect)
-    proxy = HEADER_CONNECT;
-  else
-    proxy = conn->bits.httpproxy && !conn->bits.tunnel_proxy?
-      HEADER_PROXY:HEADER_SERVER;
-
-  switch(proxy) {
-  case HEADER_SERVER:
-    h[0] = data->set.headers;
-    break;
-  case HEADER_PROXY:
-    h[0] = data->set.headers;
-    if(data->set.sep_headers) {
-      h[1] = data->set.proxyheaders;
-      numlists++;
-    }
-    break;
-  case HEADER_CONNECT:
-    if(data->set.sep_headers)
-      h[0] = data->set.proxyheaders;
-    else
-      h[0] = data->set.headers;
-    break;
-  }
-#else
-  (void)is_connect;
-  h[0] = data->set.headers;
-#endif
-
-  /* loop through one or two lists */
-  for(i = 0; i < numlists; i++) {
-    for(headers = h[i]; headers; headers = headers->next) {
-      const char *name, *value;
-      size_t namelen, valuelen;
-
-      /* There are 2 quirks in place for custom headers:
-       * 1. setting only 'name:' to suppress a header from being sent
-       * 2. setting only 'name;' to send an empty (illegal) header
-       */
-      ptr = strchr(headers->data, ':');
-      if(ptr) {
-        name = headers->data;
-        namelen = ptr - headers->data;
-        ptr++; /* pass the colon */
-        while(*ptr && ISSPACE(*ptr))
-          ptr++;
-        if(*ptr) {
-          value = ptr;
-          valuelen = strlen(value);
-        }
-        else {
-          /* quirk #1, suppress this header */
-          continue;
-        }
-      }
-      else {
-        ptr = strchr(headers->data, ';');
-
-        if(!ptr) {
-          /* neither : nor ; in provided header value. We seem
-           * to ignore this silently */
-          continue;
-        }
-
-        name = headers->data;
-        namelen = ptr - headers->data;
-        ptr++; /* pass the semicolon */
-        while(*ptr && ISSPACE(*ptr))
-          ptr++;
-        if(!*ptr) {
-          /* quirk #2, send an empty header */
-          value = "";
-          valuelen = 0;
-        }
-        else {
-          /* this may be used for something else in the future,
-           * ignore this for now */
-          continue;
-        }
-      }
-
-      DEBUGASSERT(name && value);
-      if(data->state.aptr.host &&
-         /* a Host: header was sent already, do not pass on any custom Host:
-            header as that will produce *two* in the same request! */
-         hd_name_eq(name, namelen, STRCONST("Host:")))
-        ;
-      else if(data->state.httpreq == HTTPREQ_POST_FORM &&
-              /* this header (extended by formdata.c) is sent later */
-              hd_name_eq(name, namelen, STRCONST("Content-Type:")))
-        ;
-      else if(data->state.httpreq == HTTPREQ_POST_MIME &&
-              /* this header is sent later */
-              hd_name_eq(name, namelen, STRCONST("Content-Type:")))
-        ;
-      else if(data->req.authneg &&
-              /* while doing auth neg, do not allow the custom length since
-                 we will force length zero then */
-              hd_name_eq(name, namelen, STRCONST("Content-Length:")))
-        ;
-      else if(data->state.aptr.te &&
-              /* when asking for Transfer-Encoding, do not pass on a custom
-                 Connection: */
-              hd_name_eq(name, namelen, STRCONST("Connection:")))
-        ;
-      else if((conn->httpversion >= 20) &&
-              hd_name_eq(name, namelen, STRCONST("Transfer-Encoding:")))
-        /* HTTP/2 does not support chunked requests */
-        ;
-      else if((hd_name_eq(name, namelen, STRCONST("Authorization:")) ||
-               hd_name_eq(name, namelen, STRCONST("Cookie:"))) &&
-              /* be careful of sending this potentially sensitive header to
-                 other hosts */
-              !Curl_auth_allowed_to_host(data))
-        ;
-      else {
-        CURLcode result;
-
-        result = Curl_dynhds_add(hds, name, namelen, value, valuelen);
-        if(result)
-          return result;
-      }
-    }
-  }
-
-  return CURLE_OK;
-}
-
 CURLcode Curl_add_custom_headers(struct Curl_easy *data,
                                  bool is_connect,
 #ifndef USE_HYPER
@@ -1403,13 +1246,13 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data,
   int i;
 
 #ifndef CURL_DISABLE_PROXY
-  enum proxy_use proxy;
+  enum Curl_proxy_use proxy;
 
   if(is_connect)
     proxy = HEADER_CONNECT;
   else
-    proxy = conn->bits.httpproxy && !conn->bits.tunnel_proxy?
-      HEADER_PROXY:HEADER_SERVER;
+    proxy = conn->bits.httpproxy && !conn->bits.tunnel_proxy ?
+      HEADER_PROXY : HEADER_SERVER;
 
   switch(proxy) {
   case HEADER_SERVER:
@@ -1602,7 +1445,7 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data,
   msnprintf(datestr, sizeof(datestr),
             "%s: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
             condp,
-            Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
+            Curl_wkday[tm->tm_wday ? tm->tm_wday-1 : 6],
             tm->tm_mday,
             Curl_month[tm->tm_mon],
             tm->tm_year + 1900,
@@ -1755,11 +1598,12 @@ CURLcode Curl_http_host(struct Curl_easy *data, struct connectdata *conn)
         (conn->remote_port == PORT_HTTP)) )
       /* if(HTTPS on port 443) OR (HTTP on port 80) then do not include
          the port number in the host string */
-      aptr->host = aprintf("Host: %s%s%s\r\n", conn->bits.ipv6_ip?"[":"",
-                           host, conn->bits.ipv6_ip?"]":"");
+      aptr->host = aprintf("Host: %s%s%s\r\n", conn->bits.ipv6_ip ? "[" : "",
+                           host, conn->bits.ipv6_ip ? "]" : "");
     else
-      aptr->host = aprintf("Host: %s%s%s:%d\r\n", conn->bits.ipv6_ip?"[":"",
-                           host, conn->bits.ipv6_ip?"]":"",
+      aptr->host = aprintf("Host: %s%s%s:%d\r\n",
+                           conn->bits.ipv6_ip ? "[" : "",
+                           host, conn->bits.ipv6_ip ? "]" : "",
                            conn->remote_port);
 
     if(!aptr->host)
@@ -1836,8 +1680,8 @@ CURLcode Curl_http_target(struct Curl_easy *data,
     curl_url_cleanup(h);
 
     /* target or URL */
-    result = Curl_dyn_add(r, data->set.str[STRING_TARGET]?
-      data->set.str[STRING_TARGET]:url);
+    result = Curl_dyn_add(r, data->set.str[STRING_TARGET] ?
+      data->set.str[STRING_TARGET] : url);
     free(url);
     if(result)
       return (result);
@@ -1973,11 +1817,8 @@ static CURLcode set_reader(struct Curl_easy *data, Curl_HttpReq httpreq)
 
   switch(httpreq) {
   case HTTPREQ_PUT: /* Let's PUT the data to the server! */
-    if(!postsize)
-      result = Curl_creader_set_null(data);
-    else
-      result = Curl_creader_set_fread(data, postsize);
-    return result;
+    return postsize ? Curl_creader_set_fread(data, postsize) :
+      Curl_creader_set_null(data);
 
 #if !defined(CURL_DISABLE_MIME) || !defined(CURL_DISABLE_FORM_API)
   case HTTPREQ_POST_FORM:
@@ -2010,7 +1851,7 @@ static CURLcode set_reader(struct Curl_easy *data, Curl_HttpReq httpreq)
         chunked = Curl_compareheader(ptr, STRCONST("Transfer-Encoding:"),
                                      STRCONST("chunked"));
       }
-      result = Curl_creader_set_fread(data, chunked? -1 : postsize);
+      result = Curl_creader_set_fread(data, chunked ? -1 : postsize);
     }
     return result;
 
@@ -2250,8 +2091,9 @@ CURLcode Curl_http_cookies(struct Curl_easy *data,
     addcookies = data->set.str[STRING_COOKIE];
 
   if(data->cookies || addcookies) {
-    struct Cookie *co = NULL; /* no cookies from start */
+    struct Curl_llist list;
     int count = 0;
+    int rc = 1;
 
     if(data->cookies && data->state.cookie_engine) {
       const char *host = data->state.aptr.cookiehost ?
@@ -2260,17 +2102,19 @@ CURLcode Curl_http_cookies(struct Curl_easy *data,
         conn->handler->protocol&(CURLPROTO_HTTPS|CURLPROTO_WSS) ||
         strcasecompare("localhost", host) ||
         !strcmp(host, "127.0.0.1") ||
-        !strcmp(host, "::1") ? TRUE : FALSE;
+        !strcmp(host, "::1");
       Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
-      co = Curl_cookie_getlist(data, data->cookies, host, data->state.up.path,
-                               secure_context);
+      rc = Curl_cookie_getlist(data, data->cookies, host, data->state.up.path,
+                               secure_context, &list);
       Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
     }
-    if(co) {
-      struct Cookie *store = co;
+    if(!rc) {
+      struct Curl_llist_node *n;
       size_t clen = 8; /* hold the size of the generated Cookie: header */
-      /* now loop through all cookies that matched */
-      while(co) {
+
+      /* loop through all cookies that matched */
+      for(n = Curl_llist_head(&list); n; n = Curl_node_next(n)) {
+        struct Cookie *co = Curl_node_elem(n);
         if(co->value) {
           size_t add;
           if(!count) {
@@ -2285,22 +2129,21 @@ CURLcode Curl_http_cookies(struct Curl_easy *data,
             linecap = TRUE;
             break;
           }
-          result = Curl_dyn_addf(r, "%s%s=%s", count?"; ":"",
+          result = Curl_dyn_addf(r, "%s%s=%s", count ? "; " : "",
                                  co->name, co->value);
           if(result)
             break;
           clen += add + (count ? 2 : 0);
           count++;
         }
-        co = co->next; /* next cookie please */
       }
-      Curl_cookie_freelist(store);
+      Curl_llist_destroy(&list, NULL);
     }
     if(addcookies && !result && !linecap) {
       if(!count)
         result = Curl_dyn_addn(r, STRCONST("Cookie: "));
       if(!result) {
-        result = Curl_dyn_addf(r, "%s%s", count?"; ":"", addcookies);
+        result = Curl_dyn_addf(r, "%s%s", count ? "; " : "", addcookies);
         count++;
       }
     }
@@ -2350,7 +2193,7 @@ CURLcode Curl_http_range(struct Curl_easy *data,
         /* TODO: not sure if we want to send this header during authentication
          * negotiation, but test1084 checks for it. In which case we have a
          * "null" client reader installed that gives an unexpected length. */
-        curl_off_t total_len = data->req.authneg?
+        curl_off_t total_len = data->req.authneg ?
                                data->state.infilesize :
                                (data->state.resume_from + req_clen);
         data->state.aptr.rangeline =
@@ -2582,7 +2425,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
     goto fail;
 
   p_accept = Curl_checkheaders(data,
-                               STRCONST("Accept"))?NULL:"Accept: */*\r\n";
+                               STRCONST("Accept")) ? NULL : "Accept: */*\r\n";
 
   result = Curl_http_range(data, httpreq);
   if(result)
@@ -2634,35 +2477,34 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
                   "%s",/* Alt-Used */
 
                   httpstring,
-                  (data->state.aptr.host?data->state.aptr.host:""),
+                  (data->state.aptr.host ? data->state.aptr.host : ""),
 #ifndef CURL_DISABLE_PROXY
-                  data->state.aptr.proxyuserpwd?
-                  data->state.aptr.proxyuserpwd:"",
+                  data->state.aptr.proxyuserpwd ?
+                  data->state.aptr.proxyuserpwd : "",
 #else
                   "",
 #endif
-                  data->state.aptr.userpwd?data->state.aptr.userpwd:"",
-                  (data->state.use_range && data->state.aptr.rangeline)?
-                  data->state.aptr.rangeline:"",
+                  data->state.aptr.userpwd ? data->state.aptr.userpwd : "",
+                  (data->state.use_range && data->state.aptr.rangeline) ?
+                  data->state.aptr.rangeline : "",
                   (data->set.str[STRING_USERAGENT] &&
                    *data->set.str[STRING_USERAGENT] &&
-                   data->state.aptr.uagent)?
-                  data->state.aptr.uagent:"",
-                  p_accept?p_accept:"",
-                  data->state.aptr.te?data->state.aptr.te:"",
+                   data->state.aptr.uagent) ?
+                  data->state.aptr.uagent : "",
+                  p_accept ? p_accept : "",
+                  data->state.aptr.te ? data->state.aptr.te : "",
                   (data->set.str[STRING_ENCODING] &&
                    *data->set.str[STRING_ENCODING] &&
-                   data->state.aptr.accept_encoding)?
-                  data->state.aptr.accept_encoding:"",
-                  (data->state.referer && data->state.aptr.ref)?
-                  data->state.aptr.ref:"" /* Referer: <data> */,
+                   data->state.aptr.accept_encoding) ?
+                  data->state.aptr.accept_encoding : "",
+                  (data->state.referer && data->state.aptr.ref) ?
+                  data->state.aptr.ref : "" /* Referer: <data> */,
 #ifndef CURL_DISABLE_PROXY
                   (conn->bits.httpproxy &&
                    !conn->bits.tunnel_proxy &&
                    !Curl_checkheaders(data, STRCONST("Proxy-Connection")) &&
-                   !Curl_checkProxyheaders(data,
-                                           conn,
-                                           STRCONST("Proxy-Connection")))?
+                   !Curl_checkProxyheaders(data, conn,
+                                           STRCONST("Proxy-Connection"))) ?
                   "Proxy-Connection: Keep-Alive\r\n":"",
 #else
                   "",
@@ -2697,7 +2539,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
   }
 
   result = Curl_http_cookies(data, conn, &req);
-#ifdef USE_WEBSOCKETS
+#ifndef CURL_DISABLE_WEBSOCKETS
   if(!result && conn->handler->protocol&(CURLPROTO_WS|CURLPROTO_WSS))
     result = Curl_ws_request(data, &req);
 #endif
@@ -2754,7 +2596,7 @@ checkhttpprefix(struct Curl_easy *data,
 {
   struct curl_slist *head = data->set.http200aliases;
   statusline rc = STATUS_BAD;
-  statusline onmatch = len >= 5? STATUS_DONE : STATUS_UNKNOWN;
+  statusline onmatch = len >= 5 ? STATUS_DONE : STATUS_UNKNOWN;
 
   while(head) {
     if(checkprefixmax(head->data, s, len)) {
@@ -2776,7 +2618,7 @@ checkrtspprefix(struct Curl_easy *data,
                 const char *s, size_t len)
 {
   statusline result = STATUS_BAD;
-  statusline onmatch = len >= 5? STATUS_DONE : STATUS_UNKNOWN;
+  statusline onmatch = len >= 5 ? STATUS_DONE : STATUS_UNKNOWN;
   (void)data; /* unused */
   if(checkprefixmax("RTSP/", s, len))
     result = onmatch;
@@ -2837,10 +2679,10 @@ CURLcode Curl_http_header(struct Curl_easy *data,
 #else
           0
 #endif
-        ))? HD_VAL(hd, hdlen, "Alt-Svc:") : NULL;
+        )) ? HD_VAL(hd, hdlen, "Alt-Svc:") : NULL;
     if(v) {
       /* the ALPN of the current request */
-      enum alpnid id = (conn->httpversion == 30)? ALPN_h3 :
+      enum alpnid id = (conn->httpversion == 30) ? ALPN_h3 :
                          (conn->httpversion == 20) ? ALPN_h2 : ALPN_h1;
       return Curl_altsvc_parse(data, data->asi, v, id, conn->host.name,
                                curlx_uitous((unsigned int)conn->remote_port));
@@ -2850,8 +2692,8 @@ CURLcode Curl_http_header(struct Curl_easy *data,
   case 'c':
   case 'C':
     /* Check for Content-Length: header lines to get size */
-    v = (!k->http_bodyless && !data->set.ignorecl)?
-        HD_VAL(hd, hdlen, "Content-Length:") : NULL;
+    v = (!k->http_bodyless && !data->set.ignorecl) ?
+      HD_VAL(hd, hdlen, "Content-Length:") : NULL;
     if(v) {
       curl_off_t contentlength;
       CURLofft offt = curlx_strtoofft(v, NULL, 10, &contentlength);
@@ -2876,8 +2718,8 @@ CURLcode Curl_http_header(struct Curl_easy *data,
       }
       return CURLE_OK;
     }
-    v = (!k->http_bodyless && data->set.str[STRING_ENCODING])?
-        HD_VAL(hd, hdlen, "Content-Encoding:") : NULL;
+    v = (!k->http_bodyless && data->set.str[STRING_ENCODING]) ?
+      HD_VAL(hd, hdlen, "Content-Encoding:") : NULL;
     if(v) {
       /*
        * Process Content-Encoding. Look for the values: identity,
@@ -2925,7 +2767,7 @@ CURLcode Curl_http_header(struct Curl_easy *data,
       infof(data, "HTTP/1.0 connection set to keep alive");
       return CURLE_OK;
     }
-    v = !k->http_bodyless? HD_VAL(hd, hdlen, "Content-Range:") : NULL;
+    v = !k->http_bodyless ? HD_VAL(hd, hdlen, "Content-Range:") : NULL;
     if(v) {
       /* Content-Range: bytes [num]-
          Content-Range: bytes: [num]-
@@ -2959,7 +2801,7 @@ CURLcode Curl_http_header(struct Curl_easy *data,
   case 'l':
   case 'L':
     v = (!k->http_bodyless &&
-         (data->set.timecondition || data->set.get_filetime))?
+         (data->set.timecondition || data->set.get_filetime)) ?
         HD_VAL(hd, hdlen, "Last-Modified:") : NULL;
     if(v) {
       k->timeofdoc = Curl_getdate_capped(v);
@@ -3042,8 +2884,7 @@ CURLcode Curl_http_header(struct Curl_easy *data,
         char *persistentauth = Curl_copy_header_value(hd);
         if(!persistentauth)
           return CURLE_OUT_OF_MEMORY;
-        negdata->noauthpersist = checkprefix("false", persistentauth)?
-          TRUE:FALSE;
+        negdata->noauthpersist = !!checkprefix("false", persistentauth);
         negdata->havenoauthpersist = TRUE;
         infof(data, "Negotiate: noauthpersist -> %d, header part: %s",
               negdata->noauthpersist, persistentauth);
@@ -3073,18 +2914,18 @@ CURLcode Curl_http_header(struct Curl_easy *data,
   case 's':
   case 'S':
 #if !defined(CURL_DISABLE_COOKIES)
-    v = (data->cookies && data->state.cookie_engine)?
+    v = (data->cookies && data->state.cookie_engine) ?
         HD_VAL(hd, hdlen, "Set-Cookie:") : NULL;
     if(v) {
       /* If there is a custom-set Host: name, use it here, or else use
        * real peer hostname. */
-      const char *host = data->state.aptr.cookiehost?
-        data->state.aptr.cookiehost:conn->host.name;
+      const char *host = data->state.aptr.cookiehost ?
+        data->state.aptr.cookiehost : conn->host.name;
       const bool secure_context =
         conn->handler->protocol&(CURLPROTO_HTTPS|CURLPROTO_WSS) ||
         strcasecompare("localhost", host) ||
         !strcmp(host, "127.0.0.1") ||
-        !strcmp(host, "::1") ? TRUE : FALSE;
+        !strcmp(host, "::1");
 
       Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
                       CURL_LOCK_ACCESS_SINGLE);
@@ -3105,7 +2946,7 @@ CURLcode Curl_http_header(struct Curl_easy *data,
            0
 #endif
             )
-        )? HD_VAL(hd, hdlen, "Strict-Transport-Security:") : NULL;
+        ) ? HD_VAL(hd, hdlen, "Strict-Transport-Security:") : NULL;
     if(v) {
       CURLcode check =
         Curl_hsts_parse(data->hsts, conn->host.name, v);
@@ -3133,8 +2974,8 @@ CURLcode Curl_http_header(struct Curl_easy *data,
      */
     v = (!k->http_bodyless &&
          (data->state.httpreq != HTTPREQ_HEAD) &&
-         (k->httpcode != 304))?
-        HD_VAL(hd, hdlen, "Transfer-Encoding:") : NULL;
+         (k->httpcode != 304)) ?
+      HD_VAL(hd, hdlen, "Transfer-Encoding:") : NULL;
     if(v) {
       /* One or more encodings. We check for chunked and/or a compression
          algorithm. */
@@ -3372,8 +3213,8 @@ static CURLcode http_write_header(struct Curl_easy *data,
     return result;
 
   data->req.deductheadercount = (100 <= data->req.httpcode &&
-                                 199 >= data->req.httpcode)?
-                                data->req.headerbytecount:0;
+                                 199 >= data->req.httpcode) ?
+    data->req.headerbytecount : 0;
   return result;
 }
 
@@ -3449,7 +3290,7 @@ static CURLcode http_on_response(struct Curl_easy *data,
           goto out;
         *pconsumed += blen;
       }
-#ifdef USE_WEBSOCKETS
+#ifndef CURL_DISABLE_WEBSOCKETS
       else if(k->upgr101 == UPGR101_WS) {
         /* verify the response. Any passed `buf` bytes are already in
          * WebSockets format and taken in by the protocol handler. */
@@ -3534,7 +3375,7 @@ static CURLcode http_on_response(struct Curl_easy *data,
   }
 #endif
 
-#ifdef USE_WEBSOCKETS
+#ifndef CURL_DISABLE_WEBSOCKETS
   /* All >=200 HTTP status codes are errors when wanting WebSockets */
   if(data->req.upgr101 == UPGR101_WS) {
     failf(data, "Refused WebSockets upgrade: %d", k->httpcode);
@@ -4052,7 +3893,7 @@ CURLcode Curl_http_decode_status(int *pstatus, const char *s, size_t len)
   }
   result = CURLE_OK;
 out:
-  *pstatus = result? -1 : status;
+  *pstatus = result ? -1 : status;
   return result;
 }
 
@@ -4095,7 +3936,7 @@ CURLcode Curl_http_req_make(struct httpreq **preq,
 out:
   if(result && req)
     Curl_http_req_free(req);
-  *preq = result? NULL : req;
+  *preq = result ? NULL : req;
   return result;
 }
 
@@ -4253,7 +4094,7 @@ CURLcode Curl_http_req_make2(struct httpreq **preq,
 out:
   if(result && req)
     Curl_http_req_free(req);
-  *preq = result? NULL : req;
+  *preq = result ? NULL : req;
   return result;
 }
 
@@ -4319,8 +4160,8 @@ CURLcode Curl_http_req_to_h2(struct dynhds *h2_headers,
       infof(data, "set pseudo header %s to %s", HTTP_PSEUDO_SCHEME, scheme);
     }
     else {
-      scheme = (data->conn && data->conn->handler->flags & PROTOPT_SSL)?
-                "https" : "http";
+      scheme = (data->conn && data->conn->handler->flags & PROTOPT_SSL) ?
+        "https" : "http";
     }
   }
 
@@ -4384,7 +4225,7 @@ CURLcode Curl_http_resp_make(struct http_resp **presp,
 out:
   if(result && resp)
     Curl_http_resp_free(resp);
-  *presp = result? NULL : resp;
+  *presp = result ? NULL : resp;
   return result;
 }
 
@@ -4479,7 +4320,7 @@ static void cr_exp100_done(struct Curl_easy *data,
                            struct Curl_creader *reader, int premature)
 {
   struct cr_exp100_ctx *ctx = reader->ctx;
-  ctx->state = premature? EXP100_FAILED : EXP100_SEND_DATA;
+  ctx->state = premature ? EXP100_FAILED : EXP100_SEND_DATA;
   data->req.keepon &= ~KEEP_SEND_TIMED;
   Curl_expire_done(data, EXPIRE_100_TIMEOUT);
 }
@@ -4545,7 +4386,7 @@ static void http_exp100_send_anyway(struct Curl_easy *data)
 bool Curl_http_exp100_is_selected(struct Curl_easy *data)
 {
   struct Curl_creader *r = Curl_creader_get_by_type(data, &cr_exp100);
-  return r? TRUE : FALSE;
+  return !!r;
 }
 
 #endif /* CURL_DISABLE_HTTP */

+ 0 - 3
lib/http.h

@@ -89,9 +89,6 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data,
                                  void *headers
 #endif
   );
-CURLcode Curl_dynhds_add_custom(struct Curl_easy *data,
-                                bool is_connect,
-                                struct dynhds *hds);
 
 void Curl_http_method(struct Curl_easy *data, struct connectdata *conn,
                       const char **method, Curl_HttpReq *);

+ 5 - 5
lib/http1.c

@@ -128,7 +128,7 @@ static ssize_t next_line(struct h1_req_parser *parser,
   else if(*err == CURLE_AGAIN) {
     /* no line end in `buf`, add it to our scratch */
     *err = Curl_dyn_addn(&parser->scratch, (const unsigned char *)buf, buflen);
-    nread = (*err)? -1 : (ssize_t)buflen;
+    nread = (*err) ? -1 : (ssize_t)buflen;
   }
   return nread;
 }
@@ -325,10 +325,10 @@ CURLcode Curl_h1_req_write_head(struct httpreq *req, int http_minor,
 
   result = Curl_dyn_addf(dbuf, "%s %s%s%s%s HTTP/1.%d\r\n",
                          req->method,
-                         req->scheme? req->scheme : "",
-                         req->scheme? "://" : "",
-                         req->authority? req->authority : "",
-                         req->path? req->path : "",
+                         req->scheme ? req->scheme : "",
+                         req->scheme ? "://" : "",
+                         req->authority ? req->authority : "",
+                         req->path ? req->path : "",
                          http_minor);
   if(result)
     goto out;

+ 103 - 49
lib/http2.c

@@ -254,7 +254,7 @@ static struct h2_stream_ctx *h2_stream_ctx_create(struct cf_h2_ctx *ctx)
 static void free_push_headers(struct h2_stream_ctx *stream)
 {
   size_t i;
-  for(i = 0; i<stream->push_headers_used; i++)
+  for(i = 0; i < stream->push_headers_used; i++)
     free(stream->push_headers[i]);
   Curl_safefree(stream->push_headers);
   stream->push_headers_used = 0;
@@ -299,7 +299,7 @@ static CURLcode cf_h2_update_local_win(struct Curl_cfilter *cf,
   int32_t dwsize;
   int rv;
 
-  dwsize = paused? 0 : cf_h2_get_desired_local_win(cf, data);
+  dwsize = paused ? 0 : cf_h2_get_desired_local_win(cf, data);
   if(dwsize != stream->local_window_size) {
     int32_t wsize = nghttp2_session_get_stream_effective_local_window_size(
                       ctx->h2, stream->id);
@@ -433,6 +433,8 @@ static int h2_client_new(struct Curl_cfilter *cf,
 {
   struct cf_h2_ctx *ctx = cf->ctx;
   nghttp2_option *o;
+  nghttp2_mem mem = {NULL, Curl_nghttp2_malloc, Curl_nghttp2_free,
+                     Curl_nghttp2_calloc, Curl_nghttp2_realloc};
 
   int rc = nghttp2_option_new(&o);
   if(rc)
@@ -445,7 +447,7 @@ static int h2_client_new(struct Curl_cfilter *cf,
      HTTP field value. */
   nghttp2_option_set_no_rfc9113_leading_and_trailing_ws_validation(o, 1);
 #endif
-  rc = nghttp2_session_client_new2(&ctx->h2, cbs, cf, o);
+  rc = nghttp2_session_client_new3(&ctx->h2, cbs, cf, o, &mem);
   nghttp2_option_del(o);
   return rc;
 }
@@ -498,9 +500,10 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
                      const uint8_t *value, size_t valuelen,
                      uint8_t flags,
                      void *userp);
+#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
 static int error_callback(nghttp2_session *session, const char *msg,
                           size_t len, void *userp);
-
+#endif
 static CURLcode cf_h2_ctx_open(struct Curl_cfilter *cf,
                                struct Curl_easy *data)
 {
@@ -530,7 +533,9 @@ static CURLcode cf_h2_ctx_open(struct Curl_cfilter *cf,
   nghttp2_session_callbacks_set_on_begin_headers_callback(
     cbs, on_begin_headers);
   nghttp2_session_callbacks_set_on_header_callback(cbs, on_header);
+#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
   nghttp2_session_callbacks_set_error_callback(cbs, error_callback);
+#endif
 
   /* The nghttp2 session is not yet setup, do it */
   rc = h2_client_new(cf, cbs);
@@ -606,7 +611,7 @@ static CURLcode cf_h2_ctx_open(struct Curl_cfilter *cf,
   /* all set, traffic will be send on connect */
   result = CURLE_OK;
   CURL_TRC_CF(data, cf, "[0] created h2 session%s",
-              ctx->via_h1_upgrade? " (via h1 upgrade)" : "");
+              ctx->via_h1_upgrade ? " (via h1 upgrade)" : "");
 
 out:
   if(cbs)
@@ -764,7 +769,7 @@ static CURLcode nw_out_flush(struct Curl_cfilter *cf,
     }
     return result;
   }
-  return Curl_bufq_is_empty(&ctx->outbufq)? CURLE_OK: CURLE_AGAIN;
+  return Curl_bufq_is_empty(&ctx->outbufq) ? CURLE_OK : CURLE_AGAIN;
 }
 
 /*
@@ -786,8 +791,11 @@ static ssize_t send_callback(nghttp2_session *h2,
   (void)flags;
   DEBUGASSERT(data);
 
-  nwritten = Curl_bufq_write_pass(&ctx->outbufq, buf, blen,
-                                  nw_out_writer, cf, &result);
+  if(!cf->connected)
+    nwritten = Curl_bufq_write(&ctx->outbufq, buf, blen, &result);
+  else
+    nwritten = Curl_bufq_write_pass(&ctx->outbufq, buf, blen,
+                                    nw_out_writer, cf, &result);
   if(nwritten < 0) {
     if(result == CURLE_AGAIN) {
       ctx->nw_out_blocked = 1;
@@ -852,7 +860,7 @@ char *curl_pushheader_byname(struct curl_pushheaders *h, const char *header)
     return NULL;
 
   len = strlen(header);
-  for(i = 0; i<stream->push_headers_used; i++) {
+  for(i = 0; i < stream->push_headers_used; i++) {
     if(!strncmp(header, stream->push_headers[i], len)) {
       /* sub-match, make sure that it is followed by a colon */
       if(stream->push_headers[i][len] != ':')
@@ -990,11 +998,11 @@ static int push_promise(struct Curl_cfilter *cf,
     }
     DEBUGASSERT(stream);
 
-    Curl_set_in_callback(data, true);
+    Curl_set_in_callback(data, TRUE);
     rv = data->multi->push_cb(data, newhandle,
                               stream->push_headers_used, &heads,
                               data->multi->push_userp);
-    Curl_set_in_callback(data, false);
+    Curl_set_in_callback(data, FALSE);
 
     /* free the headers again */
     free_push_headers(stream);
@@ -1113,9 +1121,6 @@ static CURLcode on_stream_frame(struct Curl_cfilter *cf,
         return CURLE_RECV_ERROR;
       }
     }
-    if(frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
-      drain_stream(cf, data, stream);
-    }
     break;
   case NGHTTP2_HEADERS:
     if(stream->bodystarted) {
@@ -1131,10 +1136,10 @@ static CURLcode on_stream_frame(struct Curl_cfilter *cf,
       return CURLE_RECV_ERROR;
 
     /* Only final status code signals the end of header */
-    if(stream->status_code / 100 != 1) {
+    if(stream->status_code / 100 != 1)
       stream->bodystarted = TRUE;
+    else
       stream->status_code = -1;
-    }
 
     h2_xfer_write_resp_hd(cf, data, stream, STRCONST("\r\n"), stream->closed);
 
@@ -1181,6 +1186,22 @@ static CURLcode on_stream_frame(struct Curl_cfilter *cf,
   default:
     break;
   }
+
+  if(frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
+    if(!stream->closed && !stream->body_eos &&
+       ((stream->status_code >= 400) || (stream->status_code < 200))) {
+      /* The server did not give us a positive response and we are not
+       * done uploading the request body. We need to stop doing that and
+       * also inform the server that we aborted our side. */
+      CURL_TRC_CF(data, cf, "[%d] EOS frame with unfinished upload and "
+                  "HTTP status %d, abort upload by RST",
+                  stream_id, stream->status_code);
+      nghttp2_submit_rst_stream(ctx->h2, NGHTTP2_FLAG_NONE,
+                                stream->id, NGHTTP2_STREAM_CLOSED);
+      stream->closed = TRUE;
+    }
+    drain_stream(cf, data, stream);
+  }
   return CURLE_OK;
 }
 
@@ -1235,14 +1256,14 @@ static int fr_print(const nghttp2_frame *frame, char *buffer, size_t blen)
     case NGHTTP2_GOAWAY: {
       char scratch[128];
       size_t s_len = sizeof(scratch)/sizeof(scratch[0]);
-        size_t len = (frame->goaway.opaque_data_len < s_len)?
-                      frame->goaway.opaque_data_len : s_len-1;
-        if(len)
-          memcpy(scratch, frame->goaway.opaque_data, len);
-        scratch[len] = '\0';
-        return msnprintf(buffer, blen, "FRAME[GOAWAY, error=%d, reason='%s', "
-                         "last_stream=%d]", frame->goaway.error_code,
-                         scratch, frame->goaway.last_stream_id);
+      size_t len = (frame->goaway.opaque_data_len < s_len) ?
+        frame->goaway.opaque_data_len : s_len-1;
+      if(len)
+        memcpy(scratch, frame->goaway.opaque_data, len);
+      scratch[len] = '\0';
+      return msnprintf(buffer, blen, "FRAME[GOAWAY, error=%d, reason='%s', "
+                       "last_stream=%d]", frame->goaway.error_code,
+                       scratch, frame->goaway.last_stream_id);
     }
     case NGHTTP2_WINDOW_UPDATE: {
       return msnprintf(buffer, blen,
@@ -1350,7 +1371,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
     return 0;
   }
 
-  return on_stream_frame(cf, data_s, frame)? NGHTTP2_ERR_CALLBACK_FAILURE : 0;
+  return on_stream_frame(cf, data_s, frame) ? NGHTTP2_ERR_CALLBACK_FAILURE : 0;
 }
 
 static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
@@ -1402,8 +1423,8 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
 
   DEBUGASSERT(call_data);
   /* stream id 0 is the connection, do not look there for streams. */
-  data_s = stream_id?
-             nghttp2_session_get_stream_user_data(session, stream_id) : NULL;
+  data_s = stream_id ?
+    nghttp2_session_get_stream_user_data(session, stream_id) : NULL;
   if(!data_s) {
     CURL_TRC_CF(call_data, cf,
                 "[%d] on_stream_close, no easy set on stream", stream_id);
@@ -1683,7 +1704,7 @@ static ssize_t req_body_read_callback(nghttp2_session *session,
     *data_flags = NGHTTP2_DATA_FLAG_EOF;
     return nread;
   }
-  return (nread == 0)? NGHTTP2_ERR_DEFERRED : nread;
+  return (nread == 0) ? NGHTTP2_ERR_DEFERRED : nread;
 }
 
 #if !defined(CURL_DISABLE_VERBOSE_STRINGS)
@@ -1773,7 +1794,7 @@ static ssize_t http2_handle_stream_close(struct Curl_cfilter *cf,
   }
   else if(stream->reset) {
     failf(data, "HTTP/2 stream %u was reset", stream->id);
-    *err = data->req.bytecount? CURLE_PARTIAL_FILE : CURLE_HTTP2;
+    *err = data->req.bytecount ? CURLE_PARTIAL_FILE : CURLE_HTTP2;
     return -1;
   }
 
@@ -1826,14 +1847,14 @@ out:
 static int sweight_wanted(const struct Curl_easy *data)
 {
   /* 0 weight is not set by user and we take the nghttp2 default one */
-  return data->set.priority.weight?
+  return data->set.priority.weight ?
     data->set.priority.weight : NGHTTP2_DEFAULT_WEIGHT;
 }
 
 static int sweight_in_effect(const struct Curl_easy *data)
 {
   /* 0 weight is not set by user and we take the nghttp2 default one */
-  return data->state.priority.weight?
+  return data->state.priority.weight ?
     data->state.priority.weight : NGHTTP2_DEFAULT_WEIGHT;
 }
 
@@ -1849,7 +1870,7 @@ static void h2_pri_spec(struct cf_h2_ctx *ctx,
 {
   struct Curl_data_priority *prio = &data->set.priority;
   struct h2_stream_ctx *depstream = H2_STREAM_CTX(ctx, prio->parent);
-  int32_t depstream_id = depstream? depstream->id:0;
+  int32_t depstream_id = depstream ? depstream->id : 0;
   nghttp2_priority_spec_init(pri_spec, depstream_id,
                              sweight_wanted(data),
                              data->set.priority.exclusive);
@@ -1895,6 +1916,11 @@ out:
                 nghttp2_strerror(rv), rv);
     return CURLE_SEND_ERROR;
   }
+  /* Defer flushing during the connect phase so that the SETTINGS and
+   * other initial frames are sent together with the first request.
+   * Unless we are 'connect_only' where the request will never come. */
+  if(!cf->connected && !cf->conn->connect_only)
+    return CURLE_OK;
   return nw_out_flush(cf, data);
 }
 
@@ -1920,7 +1946,7 @@ static ssize_t stream_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
           (ctx->conn_closed && Curl_bufq_is_empty(&ctx->inbufq)) ||
           (ctx->rcvd_goaway && ctx->remote_max_sid < stream->id)) {
     CURL_TRC_CF(data, cf, "[%d] returning ERR", stream->id);
-    *err = data->req.bytecount? CURLE_PARTIAL_FILE : CURLE_HTTP2;
+    *err = data->req.bytecount ? CURLE_PARTIAL_FILE : CURLE_HTTP2;
     nread = -1;
   }
 
@@ -1978,8 +2004,8 @@ static CURLcode h2_progress_ingress(struct Curl_cfilter *cf,
     }
     else {
       CURL_TRC_CF(data, cf, "[0] ingress: read %zd bytes", nread);
-      data_max_bytes = (data_max_bytes > (size_t)nread)?
-                        (data_max_bytes - (size_t)nread) : 0;
+      data_max_bytes = (data_max_bytes > (size_t)nread) ?
+        (data_max_bytes - (size_t)nread) : 0;
     }
 
     if(h2_process_pending_input(cf, data, &result))
@@ -2244,7 +2270,7 @@ static ssize_t h2_submit(struct h2_stream_ctx **pstream,
 
 out:
   CURL_TRC_CF(data, cf, "[%d] submit -> %zd, %d",
-              stream? stream->id : -1, nwritten, *err);
+              stream ? stream->id : -1, nwritten, *err);
   Curl_safefree(nva);
   *pstream = stream;
   Curl_dynhds_free(&h2_headers);
@@ -2436,6 +2462,7 @@ static CURLcode cf_h2_connect(struct Curl_cfilter *cf,
   struct cf_h2_ctx *ctx = cf->ctx;
   CURLcode result = CURLE_OK;
   struct cf_call_data save;
+  bool first_time = FALSE;
 
   if(cf->connected) {
     *done = TRUE;
@@ -2457,11 +2484,14 @@ static CURLcode cf_h2_connect(struct Curl_cfilter *cf,
     result = cf_h2_ctx_open(cf, data);
     if(result)
       goto out;
+    first_time = TRUE;
   }
 
-  result = h2_progress_ingress(cf, data, H2_CHUNK_SIZE);
-  if(result)
-    goto out;
+  if(!first_time) {
+    result = h2_progress_ingress(cf, data, H2_CHUNK_SIZE);
+    if(result)
+      goto out;
+  }
 
   /* Send out our SETTINGS and ACKs and such. If that blocks, we
    * have it buffered and  can count this filter as being connected */
@@ -2584,7 +2614,7 @@ static CURLcode http2_data_pause(struct Curl_cfilter *cf,
       Curl_expire(data, 0, EXPIRE_RUN_NOW);
     }
     CURL_TRC_CF(data, cf, "[%d] stream now %spaused", stream->id,
-                pause? "" : "un");
+                pause ? "" : "un");
   }
   return CURLE_OK;
 }
@@ -2630,7 +2660,7 @@ static bool cf_h2_data_pending(struct Curl_cfilter *cf,
   if(ctx && (!Curl_bufq_is_empty(&ctx->inbufq)
             || (stream && !Curl_bufq_is_empty(&stream->sendbuf))))
     return TRUE;
-  return cf->next? cf->next->cft->has_data_pending(cf->next, data) : FALSE;
+  return cf->next ? cf->next->cft->has_data_pending(cf->next, data) : FALSE;
 }
 
 static bool cf_h2_is_alive(struct Curl_cfilter *cf,
@@ -2681,12 +2711,12 @@ static CURLcode cf_h2_query(struct Curl_cfilter *cf,
     else {
       effective_max = ctx->max_concurrent_streams;
     }
-    *pres1 = (effective_max > INT_MAX)? INT_MAX : (int)effective_max;
+    *pres1 = (effective_max > INT_MAX) ? INT_MAX : (int)effective_max;
     CF_DATA_RESTORE(cf, save);
     return CURLE_OK;
   case CF_QUERY_STREAM_ERROR: {
     struct h2_stream_ctx *stream = H2_STREAM_CTX(ctx, data);
-    *pres1 = stream? (int)stream->error : 0;
+    *pres1 = stream ? (int)stream->error : 0;
     return CURLE_OK;
   }
   case CF_QUERY_NEED_FLUSH: {
@@ -2701,7 +2731,7 @@ static CURLcode cf_h2_query(struct Curl_cfilter *cf,
   default:
     break;
   }
-  return cf->next?
+  return cf->next ?
     cf->next->cft->query(cf->next, data, query, pres1, pres2) :
     CURLE_UNKNOWN_OPTION;
 }
@@ -2751,7 +2781,7 @@ static CURLcode http2_cfilter_add(struct Curl_cfilter **pcf,
 out:
   if(result)
     cf_h2_ctx_free(ctx);
-  *pcf = result? NULL : cf;
+  *pcf = result ? NULL : cf;
   return result;
 }
 
@@ -2782,8 +2812,8 @@ out:
   return result;
 }
 
-static bool Curl_cf_is_http2(struct Curl_cfilter *cf,
-                             const struct Curl_easy *data)
+static bool cf_is_http2(struct Curl_cfilter *cf,
+                        const struct Curl_easy *data)
 {
   (void)data;
   for(; cf; cf = cf->next) {
@@ -2799,7 +2829,7 @@ bool Curl_conn_is_http2(const struct Curl_easy *data,
                         const struct connectdata *conn,
                         int sockindex)
 {
-  return conn? Curl_cf_is_http2(conn->cfilter[sockindex], data) : FALSE;
+  return conn ? cf_is_http2(conn->cfilter[sockindex], data) : FALSE;
 }
 
 bool Curl_http2_may_switch(struct Curl_easy *data,
@@ -2851,7 +2881,7 @@ CURLcode Curl_http2_switch_at(struct Curl_cfilter *cf, struct Curl_easy *data)
   struct Curl_cfilter *cf_h2;
   CURLcode result;
 
-  DEBUGASSERT(!Curl_cf_is_http2(cf, data));
+  DEBUGASSERT(!cf_is_http2(cf, data));
 
   result = http2_cfilter_insert_after(cf, data, FALSE);
   if(result)
@@ -2932,6 +2962,30 @@ bool Curl_h2_http_1_1_error(struct Curl_easy *data)
   return FALSE;
 }
 
+void *Curl_nghttp2_malloc(size_t size, void *user_data)
+{
+  (void)user_data;
+  return Curl_cmalloc(size);
+}
+
+void Curl_nghttp2_free(void *ptr, void *user_data)
+{
+  (void)user_data;
+  Curl_cfree(ptr);
+}
+
+void *Curl_nghttp2_calloc(size_t nmemb, size_t size, void *user_data)
+{
+  (void)user_data;
+  return Curl_ccalloc(nmemb, size);
+}
+
+void *Curl_nghttp2_realloc(void *ptr, size_t size, void *user_data)
+{
+  (void)user_data;
+  return Curl_crealloc(ptr, size);
+}
+
 #else /* !USE_NGHTTP2 */
 
 /* Satisfy external references even if http2 is not compiled in. */

+ 5 - 0
lib/http2.h

@@ -60,6 +60,11 @@ CURLcode Curl_http2_upgrade(struct Curl_easy *data,
                             struct connectdata *conn, int sockindex,
                             const char *ptr, size_t nread);
 
+void *Curl_nghttp2_malloc(size_t size, void *user_data);
+void Curl_nghttp2_free(void *ptr, void *user_data);
+void *Curl_nghttp2_calloc(size_t nmemb, size_t size, void *user_data);
+void *Curl_nghttp2_realloc(void *ptr, size_t size, void *user_data);
+
 extern struct Curl_cftype Curl_cft_nghttp2;
 
 #else /* USE_NGHTTP2 */

+ 18 - 31
lib/http_aws_sigv4.c

@@ -47,7 +47,7 @@
 
 #define HMAC_SHA256(k, kl, d, dl, o)           \
   do {                                         \
-    result = Curl_hmacit(Curl_HMAC_SHA256,     \
+    result = Curl_hmacit(&Curl_HMAC_SHA256,    \
                          (unsigned char *)k,   \
                          kl,                   \
                          (unsigned char *)d,   \
@@ -122,10 +122,6 @@ static void trim_headers(struct curl_slist *head)
 
 #define DATE_HDR_KEY_LEN (MAX_SIGV4_LEN + sizeof("X--Date"))
 
-#define MAX_HOST_LEN 255
-/* FQDN + host: */
-#define FULL_HOST_LEN (MAX_HOST_LEN + sizeof("host:"))
-
 /* string been x-PROVIDER-date:TIMESTAMP, I need +1 for ':' */
 #define DATE_FULL_HDR_LEN (DATE_HDR_KEY_LEN + TIMESTAMP_SIZE + 1)
 
@@ -176,7 +172,7 @@ static CURLcode make_headers(struct Curl_easy *data,
   struct curl_slist *tmp_head = NULL;
   CURLcode ret = CURLE_OUT_OF_MEMORY;
   struct curl_slist *l;
-  int again = 1;
+  bool again = TRUE;
 
   /* provider1 mid */
   Curl_strntolower(provider1, provider1, strlen(provider1));
@@ -190,31 +186,22 @@ static CURLcode make_headers(struct Curl_easy *data,
             "x-%s-date:%s", provider1, timestamp);
 
   if(!Curl_checkheaders(data, STRCONST("Host"))) {
-    char full_host[FULL_HOST_LEN + 1];
+    char *fullhost;
 
     if(data->state.aptr.host) {
-      size_t pos;
-
-      if(strlen(data->state.aptr.host) > FULL_HOST_LEN) {
-        ret = CURLE_URL_MALFORMAT;
-        goto fail;
-      }
-      strcpy(full_host, data->state.aptr.host);
       /* remove /r/n as the separator for canonical request must be '\n' */
-      pos = strcspn(full_host, "\n\r");
-      full_host[pos] = 0;
-    }
-    else {
-      if(strlen(hostname) > MAX_HOST_LEN) {
-        ret = CURLE_URL_MALFORMAT;
-        goto fail;
-      }
-      msnprintf(full_host, FULL_HOST_LEN, "host:%s", hostname);
+      size_t pos = strcspn(data->state.aptr.host, "\n\r");
+      fullhost = Curl_memdup0(data->state.aptr.host, pos);
     }
+    else
+      fullhost = aprintf("host:%s", hostname);
 
-    head = curl_slist_append(NULL, full_host);
-    if(!head)
+    if(fullhost)
+      head = Curl_slist_append_nodup(NULL, fullhost);
+    if(!head) {
+      free(fullhost);
       goto fail;
+    }
   }
 
 
@@ -300,7 +287,7 @@ static CURLcode make_headers(struct Curl_easy *data,
 
   /* alpha-sort by header name in a case sensitive manner */
   do {
-    again = 0;
+    again = FALSE;
     for(l = head; l; l = l->next) {
       struct curl_slist *next = l->next;
 
@@ -309,7 +296,7 @@ static CURLcode make_headers(struct Curl_easy *data,
 
         l->data = next->data;
         next->data = tmp;
-        again = 1;
+        again = TRUE;
       }
     }
   } while(again);
@@ -507,12 +494,12 @@ static CURLcode canon_string(const char *q, size_t len,
           /* allowed as-is */
           if(*q == '=') {
             result = Curl_dyn_addn(dq, q, 1);
-            *found_equals = true;
+            *found_equals = TRUE;
             break;
           }
         }
         /* URL encode */
-        out[1] = hex[((unsigned char)*q)>>4];
+        out[1] = hex[((unsigned char)*q) >> 4];
         out[2] = hex[*q & 0xf];
         result = Curl_dyn_addn(dq, out, 3);
         break;
@@ -562,7 +549,7 @@ static CURLcode canon_query(struct Curl_easy *data,
   ap = &array[0];
   for(i = 0; !result && (i < entry); i++, ap++) {
     const char *q = ap->p;
-    bool found_equals = false;
+    bool found_equals = FALSE;
     if(!ap->len)
       continue;
     result = canon_string(q, ap->len, dq, &found_equals);
@@ -589,7 +576,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
   char provider1[MAX_SIGV4_LEN + 1]="";
   char region[MAX_SIGV4_LEN + 1]="";
   char service[MAX_SIGV4_LEN + 1]="";
-  bool sign_as_s3 = false;
+  bool sign_as_s3 = FALSE;
   const char *hostname = conn->host.name;
   time_t clock;
   struct tm tm;

+ 2 - 2
lib/http_chunks.c

@@ -516,9 +516,9 @@ static CURLcode add_last_chunk(struct Curl_easy *data,
   if(result)
     goto out;
 
-  Curl_set_in_callback(data, true);
+  Curl_set_in_callback(data, TRUE);
   rc = data->set.trailer_callback(&trailers, data->set.trailer_data);
-  Curl_set_in_callback(data, false);
+  Curl_set_in_callback(data, FALSE);
 
   if(rc != CURL_TRAILERFUNC_OK) {
     failf(data, "operation aborted by trailing headers callback");

+ 2 - 2
lib/http_digest.c

@@ -121,9 +121,9 @@ CURLcode Curl_output_digest(struct Curl_easy *data,
     passwdp = "";
 
 #if defined(USE_WINDOWS_SSPI)
-  have_chlg = digest->input_token ? TRUE : FALSE;
+  have_chlg = !!digest->input_token;
 #else
-  have_chlg = digest->nonce ? TRUE : FALSE;
+  have_chlg = !!digest->nonce;
 #endif
 
   if(!have_chlg) {

+ 3 - 3
lib/http_negotiate.c

@@ -108,9 +108,9 @@ CURLcode Curl_input_negotiate(struct Curl_easy *data, struct connectdata *conn,
   neg_ctx->sslContext = conn->sslContext;
 #endif
   /* Check if the connection is using SSL and get the channel binding data */
-#ifdef HAVE_GSSAPI
+#if defined(USE_SSL) && defined(HAVE_GSSAPI)
   if(conn->handler->flags & PROTOPT_SSL) {
-    Curl_dyn_init(&neg_ctx->channel_binding_data, SSL_CB_MAX_SIZE);
+    Curl_dyn_init(&neg_ctx->channel_binding_data, SSL_CB_MAX_SIZE + 1);
     result = Curl_ssl_get_channel_binding(
       data, FIRSTSOCKET, &neg_ctx->channel_binding_data);
     if(result) {
@@ -124,7 +124,7 @@ CURLcode Curl_input_negotiate(struct Curl_easy *data, struct connectdata *conn,
   result = Curl_auth_decode_spnego_message(data, userp, passwdp, service,
                                            host, header, neg_ctx);
 
-#ifdef HAVE_GSSAPI
+#if defined(USE_SSL) && defined(HAVE_GSSAPI)
   Curl_dyn_free(&neg_ctx->channel_binding_data);
 #endif
 

+ 148 - 5
lib/http_proxy.c

@@ -45,12 +45,155 @@
 #include "vtls/vtls.h"
 #include "transfer.h"
 #include "multiif.h"
+#include "vauth/vauth.h"
 
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
 #include "memdebug.h"
 
+static bool hd_name_eq(const char *n1, size_t n1len,
+                       const char *n2, size_t n2len)
+{
+  return (n1len == n2len) ? strncasecompare(n1, n2, n1len) : FALSE;
+}
+
+static CURLcode dynhds_add_custom(struct Curl_easy *data,
+                                  bool is_connect,
+                                  struct dynhds *hds)
+{
+  struct connectdata *conn = data->conn;
+  char *ptr;
+  struct curl_slist *h[2];
+  struct curl_slist *headers;
+  int numlists = 1; /* by default */
+  int i;
+
+  enum Curl_proxy_use proxy;
+
+  if(is_connect)
+    proxy = HEADER_CONNECT;
+  else
+    proxy = conn->bits.httpproxy && !conn->bits.tunnel_proxy ?
+      HEADER_PROXY : HEADER_SERVER;
+
+  switch(proxy) {
+  case HEADER_SERVER:
+    h[0] = data->set.headers;
+    break;
+  case HEADER_PROXY:
+    h[0] = data->set.headers;
+    if(data->set.sep_headers) {
+      h[1] = data->set.proxyheaders;
+      numlists++;
+    }
+    break;
+  case HEADER_CONNECT:
+    if(data->set.sep_headers)
+      h[0] = data->set.proxyheaders;
+    else
+      h[0] = data->set.headers;
+    break;
+  }
+
+  /* loop through one or two lists */
+  for(i = 0; i < numlists; i++) {
+    for(headers = h[i]; headers; headers = headers->next) {
+      const char *name, *value;
+      size_t namelen, valuelen;
+
+      /* There are 2 quirks in place for custom headers:
+       * 1. setting only 'name:' to suppress a header from being sent
+       * 2. setting only 'name;' to send an empty (illegal) header
+       */
+      ptr = strchr(headers->data, ':');
+      if(ptr) {
+        name = headers->data;
+        namelen = ptr - headers->data;
+        ptr++; /* pass the colon */
+        while(*ptr && ISSPACE(*ptr))
+          ptr++;
+        if(*ptr) {
+          value = ptr;
+          valuelen = strlen(value);
+        }
+        else {
+          /* quirk #1, suppress this header */
+          continue;
+        }
+      }
+      else {
+        ptr = strchr(headers->data, ';');
+
+        if(!ptr) {
+          /* neither : nor ; in provided header value. We seem
+           * to ignore this silently */
+          continue;
+        }
+
+        name = headers->data;
+        namelen = ptr - headers->data;
+        ptr++; /* pass the semicolon */
+        while(*ptr && ISSPACE(*ptr))
+          ptr++;
+        if(!*ptr) {
+          /* quirk #2, send an empty header */
+          value = "";
+          valuelen = 0;
+        }
+        else {
+          /* this may be used for something else in the future,
+           * ignore this for now */
+          continue;
+        }
+      }
+
+      DEBUGASSERT(name && value);
+      if(data->state.aptr.host &&
+         /* a Host: header was sent already, do not pass on any custom Host:
+            header as that will produce *two* in the same request! */
+         hd_name_eq(name, namelen, STRCONST("Host:")))
+        ;
+      else if(data->state.httpreq == HTTPREQ_POST_FORM &&
+              /* this header (extended by formdata.c) is sent later */
+              hd_name_eq(name, namelen, STRCONST("Content-Type:")))
+        ;
+      else if(data->state.httpreq == HTTPREQ_POST_MIME &&
+              /* this header is sent later */
+              hd_name_eq(name, namelen, STRCONST("Content-Type:")))
+        ;
+      else if(data->req.authneg &&
+              /* while doing auth neg, do not allow the custom length since
+                 we will force length zero then */
+              hd_name_eq(name, namelen, STRCONST("Content-Length:")))
+        ;
+      else if(data->state.aptr.te &&
+              /* when asking for Transfer-Encoding, do not pass on a custom
+                 Connection: */
+              hd_name_eq(name, namelen, STRCONST("Connection:")))
+        ;
+      else if((conn->httpversion >= 20) &&
+              hd_name_eq(name, namelen, STRCONST("Transfer-Encoding:")))
+        /* HTTP/2 does not support chunked requests */
+        ;
+      else if((hd_name_eq(name, namelen, STRCONST("Authorization:")) ||
+               hd_name_eq(name, namelen, STRCONST("Cookie:"))) &&
+              /* be careful of sending this potentially sensitive header to
+                 other hosts */
+              !Curl_auth_allowed_to_host(data))
+        ;
+      else {
+        CURLcode result;
+
+        result = Curl_dynhds_add(hds, name, namelen, value, valuelen);
+        if(result)
+          return result;
+      }
+    }
+  }
+
+  return CURLE_OK;
+}
 
 CURLcode Curl_http_proxy_get_destination(struct Curl_cfilter *cf,
                                          const char **phostname,
@@ -97,8 +240,8 @@ CURLcode Curl_http_proxy_create_CONNECT(struct httpreq **preq,
   if(result)
     goto out;
 
-  authority = aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname,
-                      ipv6_ip?"]":"", port);
+  authority = aprintf("%s%s%s:%d", ipv6_ip ? "[" : "", hostname,
+                      ipv6_ip ?"]" : "", port);
   if(!authority) {
     result = CURLE_OUT_OF_MEMORY;
     goto out;
@@ -146,7 +289,7 @@ CURLcode Curl_http_proxy_create_CONNECT(struct httpreq **preq,
       goto out;
   }
 
-  result = Curl_dynhds_add_custom(data, TRUE, &req->headers);
+  result = dynhds_add_custom(data, TRUE, &req->headers);
 
 out:
   if(result && req) {
@@ -185,7 +328,7 @@ connect_sub:
   *done = FALSE;
   if(!ctx->cf_protocol) {
     struct Curl_cfilter *cf_protocol = NULL;
-    int alpn = Curl_conn_cf_is_ssl(cf->next)?
+    int alpn = Curl_conn_cf_is_ssl(cf->next) ?
       cf->conn->proxy_alpn : CURL_HTTP_VERSION_1_1;
 
     /* First time call after the subchain connected */
@@ -195,7 +338,7 @@ connect_sub:
     case CURL_HTTP_VERSION_1_1:
       CURL_TRC_CF(data, cf, "installing subfilter for HTTP/1.1");
       infof(data, "CONNECT tunnel: HTTP/1.%d negotiated",
-            (alpn == CURL_HTTP_VERSION_1_0)? 0 : 1);
+            (alpn == CURL_HTTP_VERSION_1_0) ? 0 : 1);
       result = Curl_cf_h1_proxy_insert_after(cf, data);
       if(result)
         goto out;

+ 6 - 0
lib/http_proxy.h

@@ -30,6 +30,12 @@
 
 #include "urldata.h"
 
+enum Curl_proxy_use {
+  HEADER_SERVER,  /* direct to server */
+  HEADER_PROXY,   /* regular request to proxy */
+  HEADER_CONNECT  /* sending CONNECT to a proxy */
+};
+
 CURLcode Curl_http_proxy_get_destination(struct Curl_cfilter *cf,
                                          const char **phostname,
                                          int *pport, bool *pipv6_ip);

+ 13 - 13
lib/imap.c

@@ -520,8 +520,8 @@ static CURLcode imap_perform_login(struct Curl_easy *data,
   }
 
   /* Make sure the username and password are in the correct atom format */
-  user = imap_atom(conn->user, false);
-  passwd = imap_atom(conn->passwd, false);
+  user = imap_atom(conn->user, FALSE);
+  passwd = imap_atom(conn->passwd, FALSE);
 
   /* Send the LOGIN command */
   result = imap_sendf(data, "LOGIN %s %s", user ? user : "",
@@ -655,7 +655,7 @@ static CURLcode imap_perform_list(struct Curl_easy *data)
                         imap->custom_params ? imap->custom_params : "");
   else {
     /* Make sure the mailbox is in the correct atom format if necessary */
-    char *mailbox = imap->mailbox ? imap_atom(imap->mailbox, true)
+    char *mailbox = imap->mailbox ? imap_atom(imap->mailbox, TRUE)
                                   : strdup("");
     if(!mailbox)
       return CURLE_OUT_OF_MEMORY;
@@ -697,7 +697,7 @@ static CURLcode imap_perform_select(struct Curl_easy *data)
   }
 
   /* Make sure the mailbox is in the correct atom format */
-  mailbox = imap_atom(imap->mailbox, false);
+  mailbox = imap_atom(imap->mailbox, FALSE);
   if(!mailbox)
     return CURLE_OUT_OF_MEMORY;
 
@@ -809,7 +809,7 @@ static CURLcode imap_perform_append(struct Curl_easy *data)
   }
 
   /* Make sure the mailbox is in the correct atom format */
-  mailbox = imap_atom(imap->mailbox, false);
+  mailbox = imap_atom(imap->mailbox, FALSE);
   if(!mailbox)
     return CURLE_OUT_OF_MEMORY;
 
@@ -1399,7 +1399,7 @@ static CURLcode imap_multi_statemach(struct Curl_easy *data, bool *done)
   }
 
   result = Curl_pp_statemach(data, &imapc->pp, FALSE, FALSE);
-  *done = (imapc->state == IMAP_STOP) ? TRUE : FALSE;
+  *done = (imapc->state == IMAP_STOP);
 
   return result;
 }
@@ -1859,7 +1859,7 @@ static bool imap_is_bchar(char ch)
   /* Performing the alnum check with this macro is faster because of ASCII
      arithmetic */
   if(ISALNUM(ch))
-    return true;
+    return TRUE;
 
   switch(ch) {
     /* bchar */
@@ -1873,10 +1873,10 @@ static bool imap_is_bchar(char ch)
     case '+': case ',':
     /* bchar -> achar -> uchar -> pct-encoded */
     case '%': /* HEXDIG chars are already included above */
-      return true;
+      return TRUE;
 
     default:
-      return false;
+      return FALSE;
   }
 }
 
@@ -1891,7 +1891,7 @@ static CURLcode imap_parse_url_options(struct connectdata *conn)
   CURLcode result = CURLE_OK;
   struct imap_conn *imapc = &conn->proto.imapc;
   const char *ptr = conn->options;
-  bool prefer_login = false;
+  bool prefer_login = FALSE;
 
   while(!result && ptr && *ptr) {
     const char *key = ptr;
@@ -1907,16 +1907,16 @@ static CURLcode imap_parse_url_options(struct connectdata *conn)
 
     if(strncasecompare(key, "AUTH=+LOGIN", 11)) {
       /* User prefers plaintext LOGIN over any SASL, including SASL LOGIN */
-      prefer_login = true;
+      prefer_login = TRUE;
       imapc->sasl.prefmech = SASL_AUTH_NONE;
     }
     else if(strncasecompare(key, "AUTH=", 5)) {
-      prefer_login = false;
+      prefer_login = FALSE;
       result = Curl_sasl_parse_url_auth_option(&imapc->sasl,
                                                value, ptr - value);
     }
     else {
-      prefer_login = false;
+      prefer_login = FALSE;
       result = CURLE_URL_MALFORMAT;
     }
 

+ 25 - 25
lib/krb5.c

@@ -202,14 +202,15 @@ krb5_auth(void *app_data, struct Curl_easy *data, struct connectdata *conn)
                         data->set.str[STRING_SERVICE_NAME] :
                         "ftp";
   const char *srv_host = "host";
-  gss_buffer_desc input_buffer, output_buffer, _gssresp, *gssresp;
+  gss_buffer_desc input_buffer, output_buffer, *gssresp;
+  gss_buffer_desc _gssresp = GSS_C_EMPTY_BUFFER;
   OM_uint32 maj, min;
   gss_name_t gssname;
   gss_ctx_id_t *context = app_data;
   struct gss_channel_bindings_struct chan;
   size_t base64_sz = 0;
   struct sockaddr_in *remote_addr =
-    (struct sockaddr_in *)(void *)&conn->remote_addr->sa_addr;
+    (struct sockaddr_in *)(void *)&conn->remote_addr->curl_sa_addr;
   char *stringp;
 
   if(getsockname(conn->sock[FIRSTSOCKET],
@@ -363,7 +364,7 @@ krb5_auth(void *app_data, struct Curl_easy *data, struct connectdata *conn)
       free(_gssresp.value);
 
     if(ret == AUTH_OK || service == srv_host)
-      return ret;
+      break;
 
     service = srv_host;
   }
@@ -372,13 +373,13 @@ krb5_auth(void *app_data, struct Curl_easy *data, struct connectdata *conn)
 
 static void krb5_end(void *app_data)
 {
-    OM_uint32 min;
-    gss_ctx_id_t *context = app_data;
-    if(*context != GSS_C_NO_CONTEXT) {
-      OM_uint32 maj = gss_delete_sec_context(&min, context, GSS_C_NO_BUFFER);
-      (void)maj;
-      DEBUGASSERT(maj == GSS_S_COMPLETE);
-    }
+  OM_uint32 min;
+  gss_ctx_id_t *context = app_data;
+  if(*context != GSS_C_NO_CONTEXT) {
+    OM_uint32 maj = gss_delete_sec_context(&min, context, GSS_C_NO_BUFFER);
+    (void)maj;
+    DEBUGASSERT(maj == GSS_S_COMPLETE);
+  }
 }
 
 static const struct Curl_sec_client_mech Curl_krb5_client_mech = {
@@ -612,10 +613,10 @@ static ssize_t sec_recv(struct Curl_easy *data, int sockindex,
   return total_read;
 }
 
-/* Send |length| bytes from |from| to the |fd| socket taking care of encoding
-   and negotiating with the server. |from| can be NULL. */
+/* Send |length| bytes from |from| to the |sockindex| socket taking care of
+   encoding and negotiating with the server. |from| can be NULL. */
 static void do_sec_send(struct Curl_easy *data, struct connectdata *conn,
-                        curl_socket_t fd, const char *from, int length)
+                        int sockindex, const char *from, int length)
 {
   int bytes, htonl_bytes; /* 32-bit integers for htonl */
   char *buffer = NULL;
@@ -623,7 +624,7 @@ static void do_sec_send(struct Curl_easy *data, struct connectdata *conn,
   size_t cmd_size = 0;
   CURLcode error;
   enum protection_level prot_level = conn->data_prot;
-  bool iscmd = (prot_level == PROT_CMD)?TRUE:FALSE;
+  bool iscmd = (prot_level == PROT_CMD);
 
   DEBUGASSERT(prot_level > PROT_NONE && prot_level < PROT_LAST);
 
@@ -649,27 +650,27 @@ static void do_sec_send(struct Curl_easy *data, struct connectdata *conn,
       static const char *enc = "ENC ";
       static const char *mic = "MIC ";
       if(prot_level == PROT_PRIVATE)
-        socket_write(data, fd, enc, 4);
+        socket_write(data, sockindex, enc, 4);
       else
-        socket_write(data, fd, mic, 4);
+        socket_write(data, sockindex, mic, 4);
 
-      socket_write(data, fd, cmd_buffer, cmd_size);
-      socket_write(data, fd, "\r\n", 2);
-      infof(data, "Send: %s%s", prot_level == PROT_PRIVATE?enc:mic,
+      socket_write(data, sockindex, cmd_buffer, cmd_size);
+      socket_write(data, sockindex, "\r\n", 2);
+      infof(data, "Send: %s%s", prot_level == PROT_PRIVATE ? enc : mic,
             cmd_buffer);
       free(cmd_buffer);
     }
   }
   else {
     htonl_bytes = (int)htonl((OM_uint32)bytes);
-    socket_write(data, fd, &htonl_bytes, sizeof(htonl_bytes));
-    socket_write(data, fd, buffer, curlx_sitouz(bytes));
+    socket_write(data, sockindex, &htonl_bytes, sizeof(htonl_bytes));
+    socket_write(data, sockindex, buffer, curlx_sitouz(bytes));
   }
   free(buffer);
 }
 
 static ssize_t sec_write(struct Curl_easy *data, struct connectdata *conn,
-                         curl_socket_t fd, const char *buffer, size_t length)
+                         int sockindex, const char *buffer, size_t length)
 {
   ssize_t tx = 0, len = conn->buffer_size;
 
@@ -679,7 +680,7 @@ static ssize_t sec_write(struct Curl_easy *data, struct connectdata *conn,
     if(length < (size_t)len)
       len = length;
 
-    do_sec_send(data, conn, fd, buffer, curlx_sztosi(len));
+    do_sec_send(data, conn, sockindex, buffer, curlx_sztosi(len));
     length -= len;
     buffer += len;
     tx += len;
@@ -693,10 +694,9 @@ static ssize_t sec_send(struct Curl_easy *data, int sockindex,
                         CURLcode *err)
 {
   struct connectdata *conn = data->conn;
-  curl_socket_t fd = conn->sock[sockindex];
   (void)eos; /* unused */
   *err = CURLE_OK;
-  return sec_write(data, conn, fd, buffer, len);
+  return sec_write(data, conn, sockindex, buffer, len);
 }
 
 int Curl_sec_read_msg(struct Curl_easy *data, struct connectdata *conn,

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно