From 7ceb56989f8ab3a4e1b1f2c48c9a0f382b85ec04 Mon Sep 17 00:00:00 2001
From: Curl Upstream <curl-library@cool.haxx.se>
Date: Wed, 19 Aug 2020 09:37:28 +0200
Subject: curl 2020-08-19 (9d954e49)

Code extracted from:

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

at commit 9d954e49bce3706a9a2efb119ecd05767f0f2a9e (curl-7_72_0).
---
 CMake/FindZstd.cmake       |  69 ++++++++++++++
 CMakeLists.txt             |  56 +++++++++--
 include/curl/curl.h        |  17 ++--
 include/curl/curlver.h     |   8 +-
 include/curl/multi.h       |  10 +-
 lib/Makefile.inc           |   5 +-
 lib/asyn-ares.c            |   8 +-
 lib/asyn.h                 |   1 -
 lib/connect.c              |  29 +++---
 lib/content_encoding.c     |  96 +++++++++++++++++++
 lib/curl_config.h.cmake    |   3 +
 lib/curl_setup.h           |   2 +-
 lib/curl_sspi.c            |   3 +-
 lib/curlx.h                |   3 +
 lib/doh.c                  |   4 +-
 lib/dynbuf.h               |   4 +-
 lib/easy.c                 |   3 +-
 lib/ftp.c                  |   6 +-
 lib/getinfo.c              |  29 ++++++
 lib/http.c                 |   3 -
 lib/http.h                 |   1 +
 lib/http2.c                |  80 ++++++++++++----
 lib/md4.c                  |   4 +-
 lib/md5.c                  |   4 +-
 lib/memdebug.c             |  10 ++
 lib/memdebug.h             |   5 +-
 lib/mprintf.c              |  26 ++++--
 lib/multi.c                |  62 ++++++++-----
 lib/multihandle.h          |   2 +-
 lib/parsedate.c            |   3 +-
 lib/rename.c               |  15 ++-
 lib/setopt.c               |   2 +
 lib/smtp.c                 |   6 +-
 lib/socks.c                |   6 +-
 lib/strdup.c               |  13 +--
 lib/system_win32.c         | 197 +--------------------------------------
 lib/system_win32.h         |  24 +----
 lib/transfer.c             |  17 +++-
 lib/url.c                  |   9 +-
 lib/urldata.h              |   6 +-
 lib/vauth/ntlm.c           |   1 +
 lib/version.c              |  47 +++++++++-
 lib/version_win32.c        | 226 +++++++++++++++++++++++++++++++++++++++++++++
 lib/version_win32.h        |  53 +++++++++++
 lib/vquic/ngtcp2.c         |  19 ++--
 lib/vquic/ngtcp2.h         |   2 +-
 lib/vquic/quiche.c         |  10 +-
 lib/vssh/libssh2.c         |   2 +-
 lib/vtls/bearssl.c         |  11 ++-
 lib/vtls/gtls.c            |  54 ++++++++---
 lib/vtls/nss.c             |  44 +++++++--
 lib/vtls/openssl.c         |   7 +-
 lib/vtls/schannel.c        |  20 ++--
 lib/vtls/schannel_verify.c |   8 +-
 lib/vtls/vtls.c            |   1 +
 55 files changed, 940 insertions(+), 416 deletions(-)
 create mode 100644 CMake/FindZstd.cmake
 create mode 100644 lib/version_win32.c
 create mode 100644 lib/version_win32.h

diff --git a/CMake/FindZstd.cmake b/CMake/FindZstd.cmake
new file mode 100644
index 0000000..44c741a
--- /dev/null
+++ b/CMake/FindZstd.cmake
@@ -0,0 +1,69 @@
+#***************************************************************************
+#                                  _   _ ____  _
+#  Project                     ___| | | |  _ \| |
+#                             / __| | | | |_) | |
+#                            | (__| |_| |  _ <| |___
+#                             \___|\___/|_| \_\_____|
+#
+# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.haxx.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+###########################################################################
+
+#[=======================================================================[.rst:
+FindZstd
+----------
+
+Find the zstd library
+
+Result Variables
+^^^^^^^^^^^^^^^^
+
+``Zstd_FOUND``
+  System has zstd
+``Zstd_INCLUDE_DIRS``
+  The zstd include directories.
+``Zstd_LIBRARIES``
+  The libraries needed to use zstd
+#]=======================================================================]
+
+if(UNIX)
+  find_package(PkgConfig QUIET)
+  pkg_search_module(PC_Zstd libzstd)
+endif()
+
+find_path(Zstd_INCLUDE_DIR zstd.h
+  HINTS
+    ${PC_Zstd_INCLUDEDIR}
+    ${PC_Zstd_INCLUDE_DIRS}
+)
+
+find_library(Zstd_LIBRARY NAMES zstd
+  HINTS
+    ${PC_Zstd_LIBDIR}
+    ${PC_Zstd_LIBRARY_DIRS}
+)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(Zstd
+  REQUIRED_VARS
+    Zstd_LIBRARY
+    Zstd_INCLUDE_DIR
+)
+
+if(Zstd_FOUND)
+  set(Zstd_LIBRARIES    ${Zstd_LIBRARY})
+  set(Zstd_INCLUDE_DIRS ${Zstd_INCLUDE_DIR})
+endif()
+
+mark_as_advanced(Zstd_INCLUDE_DIRS Zstd_LIBRARIES)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5a13333..68842ee 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -82,12 +82,15 @@ if(WIN32)
   set(CURL_TARGET_WINDOWS_VERSION "" CACHE STRING "Minimum target Windows version as hex string")
   if(CURL_TARGET_WINDOWS_VERSION)
     add_definitions(-D_WIN32_WINNT=${CURL_TARGET_WINDOWS_VERSION})
+    set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_WIN32_WINNT=${CURL_TARGET_WINDOWS_VERSION}")
   elseif(ENABLE_INET_PTON)
     # _WIN32_WINNT_VISTA (0x0600)
     add_definitions(-D_WIN32_WINNT=0x0600)
+    set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_WIN32_WINNT=0x0600")
   else()
     # _WIN32_WINNT_WINXP (0x0501)
     add_definitions(-D_WIN32_WINNT=0x0501)
+    set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_WIN32_WINNT=0x0501")
   endif()
 endif()
 option(CURL_LTO "Turn on compiler Link Time Optimizations" OFF)
@@ -101,7 +104,7 @@ option(ENABLE_CURLDEBUG "Set to ON to build with TrackMemory feature enabled" OF
 
 if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG)
   if(PICKY_COMPILER)
-    foreach(_CCOPT -pedantic -Wall -W -Wpointer-arith -Wwrite-strings -Wunused -Wshadow -Winline -Wnested-externs -Wmissing-declarations -Wmissing-prototypes -Wno-long-long -Wfloat-equal -Wno-multichar -Wsign-compare -Wundef -Wno-format-nonliteral -Wendif-labels -Wstrict-prototypes -Wdeclaration-after-statement -Wstrict-aliasing=3 -Wcast-align -Wtype-limits -Wold-style-declaration -Wmissing-parameter-type -Wempty-body -Wclobbered -Wignored-qualifiers -Wconversion -Wno-sign-conversion -Wvla -Wdouble-promotion -Wno-system-headers -Wno-pedantic-ms-format)
+    foreach(_CCOPT -pedantic -Wall -W -Wpointer-arith -Wwrite-strings -Wunused -Wshadow -Winline -Wnested-externs -Wmissing-declarations -Wmissing-prototypes -Wfloat-equal -Wsign-compare -Wundef -Wendif-labels -Wstrict-prototypes -Wdeclaration-after-statement -Wstrict-aliasing=3 -Wcast-align -Wtype-limits -Wold-style-declaration -Wmissing-parameter-type -Wempty-body -Wclobbered -Wignored-qualifiers -Wconversion -Wvla -Wdouble-promotion)
       # surprisingly, CHECK_C_COMPILER_FLAG needs a new variable to store each new
       # test result in.
       string(MAKE_C_IDENTIFIER "OPT${_CCOPT}" _optvarname)
@@ -110,6 +113,15 @@ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG)
         set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_CCOPT}")
       endif()
     endforeach()
+    foreach(_CCOPT long-long multichar format-nonliteral sign-conversion system-headers pedantic-ms-format)
+      # GCC only warns about unknown -Wno- options if there are also other diagnostic messages,
+      # so test for the positive form instead
+      string(MAKE_C_IDENTIFIER "OPT${_CCOPT}" _optvarname)
+      check_c_compiler_flag("-W${_CCOPT}" ${_optvarname})
+      if(${_optvarname})
+        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-${_CCOPT}")
+      endif()
+    endforeach()
   endif()
 endif()
 
@@ -213,7 +225,10 @@ if(ENABLE_IPV6 AND NOT WIN32)
   endif()
 endif()
 
-curl_nroff_check()
+if(USE_MANUAL)
+    #nroff is currently only used when USE_MANUAL is set, so we can prevent the warning of no *NROFF if USE_MANUAL is OFF (or not defined), by not even looking for NROFF..
+    curl_nroff_check()
+endif()
 find_package(Perl)
 
 cmake_dependent_option(ENABLE_MANUAL "to provide the built-in manual"
@@ -297,14 +312,17 @@ endif()
 
 # check SSL libraries
 # TODO support GnuTLS
+if(CMAKE_USE_WINSSL)
+  message(FATAL_ERROR "The cmake option CMAKE_USE_WINSSL was renamed to CMAKE_USE_SCHANNEL.")
+endif()
 
 if(APPLE)
   option(CMAKE_USE_SECTRANSP "enable Apple OS native SSL/TLS" OFF)
 endif()
 if(WIN32)
-  option(CMAKE_USE_WINSSL "enable Windows native SSL/TLS" OFF)
+  option(CMAKE_USE_SCHANNEL "enable Windows native SSL/TLS" OFF)
   cmake_dependent_option(CURL_WINDOWS_SSPI "Use windows libraries to allow NTLM authentication without openssl" ON
-    CMAKE_USE_WINSSL OFF)
+    CMAKE_USE_SCHANNEL OFF)
 endif()
 option(CMAKE_USE_MBEDTLS "Enable mbedTLS for SSL/TLS" OFF)
 option(CMAKE_USE_BEARSSL "Enable BearSSL for SSL/TLS" OFF)
@@ -312,13 +330,13 @@ option(CMAKE_USE_NSS "Enable NSS for SSL/TLS" OFF)
 option(CMAKE_USE_WOLFSSL "enable wolfSSL for SSL/TLS" OFF)
 
 set(openssl_default ON)
-if(WIN32 OR CMAKE_USE_SECTRANSP OR CMAKE_USE_WINSSL OR CMAKE_USE_MBEDTLS OR CMAKE_USE_NSS OR CMAKE_USE_WOLFSSL)
+if(WIN32 OR CMAKE_USE_SECTRANSP OR CMAKE_USE_SCHANNEL OR CMAKE_USE_MBEDTLS OR CMAKE_USE_NSS OR CMAKE_USE_WOLFSSL)
   set(openssl_default OFF)
 endif()
 option(CMAKE_USE_OPENSSL "Use OpenSSL code. Experimental" ${openssl_default})
 
 count_true(enabled_ssl_options_count
-  CMAKE_USE_WINSSL
+  CMAKE_USE_SCHANNEL
   CMAKE_USE_SECTRANSP
   CMAKE_USE_OPENSSL
   CMAKE_USE_MBEDTLS
@@ -330,10 +348,10 @@ if(enabled_ssl_options_count GREATER "1")
   set(CURL_WITH_MULTI_SSL ON)
 endif()
 
-if(CMAKE_USE_WINSSL)
+if(CMAKE_USE_SCHANNEL)
   set(SSL_ENABLED ON)
   set(USE_SCHANNEL ON) # Windows native SSL/TLS support
-  set(USE_WINDOWS_SSPI ON) # CMAKE_USE_WINSSL implies CURL_WINDOWS_SSPI
+  set(USE_WINDOWS_SSPI ON) # CMAKE_USE_SCHANNEL implies CURL_WINDOWS_SSPI
   list(APPEND CURL_LIBS "crypt32")
 endif()
 if(CURL_WINDOWS_SSPI)
@@ -638,6 +656,22 @@ if(CURL_BROTLI)
   endif()
 endif()
 
+option(CURL_ZSTD "Set to ON to enable building curl with zstd support." OFF)
+set(HAVE_ZSTD OFF)
+if(CURL_ZSTD)
+  find_package(Zstd REQUIRED)
+  cmake_push_check_state()
+  set(CMAKE_REQUIRED_INCLUDES ${Zstd_INCLUDE_DIRS})
+  set(CMAKE_REQUIRED_LIBRARIES ${Zstd_LIBRARIES})
+  check_symbol_exists(ZSTD_createDStream "zstd.h" HAVE_ZSTD_CREATEDSTREAM)
+  cmake_pop_check_state()
+  if(Zstd_FOUND AND HAVE_ZSTD_CREATEDSTREAM)
+    set(HAVE_ZSTD ON)
+    list(APPEND CURL_LIBS ${Zstd_LIBRARIES})
+    include_directories(${Zstd_INCLUDE_DIRS})
+  endif()
+endif()
+
 #libSSH2
 option(CMAKE_USE_LIBSSH2 "Use libSSH2" ON)
 mark_as_advanced(CMAKE_USE_LIBSSH2)
@@ -1319,11 +1353,13 @@ _add_if("SSL"           SSL_ENABLED)
 _add_if("IPv6"          ENABLE_IPV6)
 _add_if("unix-sockets"  USE_UNIX_SOCKETS)
 _add_if("libz"          HAVE_LIBZ)
+_add_if("brotli"        HAVE_BROTLI)
+_add_if("zstd"          HAVE_ZSTD)
 _add_if("AsynchDNS"     USE_ARES OR USE_THREADS_POSIX OR USE_THREADS_WIN32)
 _add_if("IDN"           HAVE_LIBIDN2)
 _add_if("Largefile"     (CURL_SIZEOF_CURL_OFF_T GREATER 4) AND
                         ((SIZEOF_OFF_T GREATER 4) OR USE_WIN32_LARGE_FILES))
-# TODO SSP1 (WinSSL) check is missing
+# TODO SSP1 (Schannel) check is missing
 _add_if("SSPI"          USE_WINDOWS_SSPI)
 _add_if("GSS-API"       HAVE_GSSAPI)
 _add_if("alt-svc"       ENABLE_ALT_SVC)
@@ -1385,7 +1421,7 @@ message(STATUS "Enabled protocols: ${SUPPORT_PROTOCOLS}")
 
 # Clear list and collect SSL backends
 set(_items)
-_add_if("WinSSL"           SSL_ENABLED AND USE_WINDOWS_SSPI)
+_add_if("Schannel"         SSL_ENABLED AND USE_WINDOWS_SSPI)
 _add_if("OpenSSL"          SSL_ENABLED AND USE_OPENSSL)
 _add_if("Secure Transport" SSL_ENABLED AND USE_SECTRANSP)
 _add_if("mbedTLS"          SSL_ENABLED AND USE_MBEDTLS)
diff --git a/include/curl/curl.h b/include/curl/curl.h
index e3531f5..5aeaca9 100644
--- a/include/curl/curl.h
+++ b/include/curl/curl.h
@@ -2634,10 +2634,6 @@ typedef enum {
   CURLINFO_PROXY_SSL_VERIFYRESULT = CURLINFO_LONG + 47,
   CURLINFO_PROTOCOL         = CURLINFO_LONG   + 48,
   CURLINFO_SCHEME           = CURLINFO_STRING + 49,
-  /* Fill in new entries below here! */
-
-  /* Preferably these would be defined conditionally based on the
-     sizeof curl_off_t being 64-bits */
   CURLINFO_TOTAL_TIME_T     = CURLINFO_OFF_T + 50,
   CURLINFO_NAMELOOKUP_TIME_T = CURLINFO_OFF_T + 51,
   CURLINFO_CONNECT_TIME_T   = CURLINFO_OFF_T + 52,
@@ -2646,8 +2642,9 @@ typedef enum {
   CURLINFO_REDIRECT_TIME_T  = CURLINFO_OFF_T + 55,
   CURLINFO_APPCONNECT_TIME_T = CURLINFO_OFF_T + 56,
   CURLINFO_RETRY_AFTER      = CURLINFO_OFF_T + 57,
+  CURLINFO_EFFECTIVE_METHOD = CURLINFO_STRING + 58,
 
-  CURLINFO_LASTONE          = 57
+  CURLINFO_LASTONE          = 58
 } CURLINFO;
 
 /* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
@@ -2748,6 +2745,7 @@ typedef enum {
   CURLVERSION_FIFTH,
   CURLVERSION_SIXTH,
   CURLVERSION_SEVENTH,
+  CURLVERSION_EIGHTH,
   CURLVERSION_LAST /* never actually use this */
 } CURLversion;
 
@@ -2756,7 +2754,7 @@ typedef enum {
    meant to be a built-in version number for what kind of struct the caller
    expects. If the struct ever changes, we redefine the NOW to another enum
    from above. */
-#define CURLVERSION_NOW CURLVERSION_SEVENTH
+#define CURLVERSION_NOW CURLVERSION_EIGHTH
 
 struct curl_version_info_data {
   CURLversion age;          /* age of the returned struct */
@@ -2802,6 +2800,11 @@ struct curl_version_info_data {
   const char *capath;          /* the built-in default CURLOPT_CAPATH, might
                                   be NULL */
 
+  /* These fields were added in CURLVERSION_EIGHTH */
+  unsigned int zstd_ver_num; /* Numeric Zstd version
+                                  (MAJOR << 24) | (MINOR << 12) | PATCH */
+  const char *zstd_version; /* human readable string. */
+
 };
 typedef struct curl_version_info_data curl_version_info_data;
 
@@ -2836,6 +2839,8 @@ typedef struct curl_version_info_data curl_version_info_data;
 #define CURL_VERSION_BROTLI       (1<<23) /* Brotli features are present. */
 #define CURL_VERSION_ALTSVC       (1<<24) /* Alt-Svc handling built-in */
 #define CURL_VERSION_HTTP3        (1<<25) /* HTTP3 support built-in */
+#define CURL_VERSION_ZSTD         (1<<26) /* zstd features are present */
+#define CURL_VERSION_UNICODE      (1<<27) /* Unicode support on Windows */
 
  /*
  * NAME curl_version_info()
diff --git a/include/curl/curlver.h b/include/curl/curlver.h
index fe29f0f..b9fd7e6 100644
--- a/include/curl/curlver.h
+++ b/include/curl/curlver.h
@@ -30,13 +30,13 @@
 
 /* This is the version number of the libcurl package from which this header
    file origins: */
-#define LIBCURL_VERSION "7.71.1-DEV"
+#define LIBCURL_VERSION "7.72.0-DEV"
 
 /* The numeric version number is also available "in parts" by using these
    defines: */
 #define LIBCURL_VERSION_MAJOR 7
-#define LIBCURL_VERSION_MINOR 71
-#define LIBCURL_VERSION_PATCH 1
+#define LIBCURL_VERSION_MINOR 72
+#define LIBCURL_VERSION_PATCH 0
 
 /* This is the numeric version of the libcurl version number, meant for easier
    parsing and comparisons by programs. The LIBCURL_VERSION_NUM define will
@@ -57,7 +57,7 @@
    CURL_VERSION_BITS() macro since curl's own configure script greps for it
    and needs it to contain the full number.
 */
-#define LIBCURL_VERSION_NUM 0x074701
+#define LIBCURL_VERSION_NUM 0x074800
 
 /*
  * This is the date and time when the full source package was created. The
diff --git a/include/curl/multi.h b/include/curl/multi.h
index 2e6bb72..b911ba9 100644
--- a/include/curl/multi.h
+++ b/include/curl/multi.h
@@ -427,12 +427,14 @@ CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle,
  * Name: curl_push_callback
  *
  * Desc: This callback gets called when a new stream is being pushed by the
- *       server. It approves or denies the new stream.
+ *       server. It approves or denies the new stream. It can also decide
+ *       to completely fail the connection.
  *
- * Returns: CURL_PUSH_OK or CURL_PUSH_DENY.
+ * Returns: CURL_PUSH_OK, CURL_PUSH_DENY or CURL_PUSH_ERROROUT
  */
-#define CURL_PUSH_OK   0
-#define CURL_PUSH_DENY 1
+#define CURL_PUSH_OK       0
+#define CURL_PUSH_DENY     1
+#define CURL_PUSH_ERROROUT 2 /* added in 7.72.0 */
 
 struct curl_pushheaders;  /* forward declaration only */
 
diff --git a/lib/Makefile.inc b/lib/Makefile.inc
index 723b826..ae3f961 100644
--- a/lib/Makefile.inc
+++ b/lib/Makefile.inc
@@ -60,7 +60,8 @@ LIB_CFILES = altsvc.c amigaos.c asyn-ares.c asyn-thread.c base64.c            \
   sendf.c setopt.c sha256.c share.c slist.c smb.c smtp.c socketpair.c socks.c \
   socks_gssapi.c socks_sspi.c speedcheck.c splay.c strcase.c strdup.c         \
   strerror.c strtok.c strtoofft.c system_win32.c telnet.c tftp.c timeval.c    \
-  transfer.c urlapi.c version.c warnless.c wildcard.c x509asn1.c dynbuf.c
+  transfer.c urlapi.c version.c warnless.c wildcard.c x509asn1.c dynbuf.c     \
+  version_win32.c
 
 LIB_HFILES = altsvc.h amigaos.h arpa_telnet.h asyn.h conncache.h connect.h    \
   content_encoding.h cookie.h curl_addrinfo.h curl_base64.h curl_ctype.h      \
@@ -79,7 +80,7 @@ LIB_HFILES = altsvc.h amigaos.h arpa_telnet.h asyn.h conncache.h connect.h    \
   smb.h smtp.h sockaddr.h socketpair.h socks.h speedcheck.h splay.h strcase.h \
   strdup.h strerror.h strtok.h strtoofft.h system_win32.h telnet.h tftp.h     \
   timeval.h transfer.h urlapi-int.h urldata.h warnless.h wildcard.h           \
-  x509asn1.h dynbuf.h
+  x509asn1.h dynbuf.h version_win32.h
 
 LIB_RCFILES = libcurl.rc
 
diff --git a/lib/asyn-ares.c b/lib/asyn-ares.c
index ba5160b..e651507 100644
--- a/lib/asyn-ares.c
+++ b/lib/asyn-ares.c
@@ -633,7 +633,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
 
   *waitp = 0; /* default to synchronous response */
 
-#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */
+#ifdef ENABLE_IPV6
   switch(conn->ip_version) {
   default:
 #if ARES_VERSION >= 0x010601
@@ -649,7 +649,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
     family = PF_INET6;
     break;
   }
-#endif /* CURLRES_IPV6 */
+#endif /* ENABLE_IPV6 */
 
   bufp = strdup(hostname);
   if(bufp) {
@@ -670,7 +670,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
 
     /* initial status - failed */
     res->last_status = ARES_ENOTFOUND;
-#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */
+#ifdef ENABLE_IPV6
     if(family == PF_UNSPEC) {
       if(Curl_ipv6works(conn)) {
         res->num_pending = 2;
@@ -690,7 +690,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
       }
     }
     else
-#endif /* CURLRES_IPV6 */
+#endif /* ENABLE_IPV6 */
     {
       res->num_pending = 1;
 
diff --git a/lib/asyn.h b/lib/asyn.h
index be2796c..bd3c3c1 100644
--- a/lib/asyn.h
+++ b/lib/asyn.h
@@ -164,7 +164,6 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
 #define Curl_resolver_kill(x) Curl_nop_stmt
 #define Curl_resolver_is_resolved(x,y) CURLE_COULDNT_RESOLVE_HOST
 #define Curl_resolver_wait_resolv(x,y) CURLE_COULDNT_RESOLVE_HOST
-#define Curl_resolver_getsock(x,y,z) 0
 #define Curl_resolver_duphandle(x,y,z) CURLE_OK
 #define Curl_resolver_init(x,y) CURLE_OK
 #define Curl_resolver_global_init() CURLE_OK
diff --git a/lib/connect.c b/lib/connect.c
index 29293f0..b000b1b 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -74,7 +74,7 @@
 #include "warnless.h"
 #include "conncache.h"
 #include "multihandle.h"
-#include "system_win32.h"
+#include "version_win32.h"
 #include "quic.h"
 #include "socks.h"
 
@@ -934,10 +934,10 @@ CURLcode Curl_is_connected(struct connectdata *conn,
 
         return CURLE_OK;
       }
-      infof(data, "Connection failed\n");
     }
-    else if(rc & CURL_CSELECT_ERR)
+    else if(rc & CURL_CSELECT_ERR) {
       (void)verifyconnect(conn->tempsock[i], &error);
+    }
 
     /*
      * The connection failed here, we should attempt to connect to the "next
@@ -1085,8 +1085,8 @@ void Curl_sndbufset(curl_socket_t sockfd)
   static int detectOsState = DETECT_OS_NONE;
 
   if(detectOsState == DETECT_OS_NONE) {
-    if(Curl_verify_windows_version(6, 0, PLATFORM_WINNT,
-                                   VERSION_GREATER_THAN_EQUAL))
+    if(curlx_verify_windows_version(6, 0, PLATFORM_WINNT,
+                                    VERSION_GREATER_THAN_EQUAL))
       detectOsState = DETECT_OS_VISTA_OR_LATER;
     else
       detectOsState = DETECT_OS_PREVISTA;
@@ -1363,15 +1363,15 @@ CURLcode Curl_connecthost(struct connectdata *conn,  /* context */
 }
 
 struct connfind {
-  struct connectdata *tofind;
-  bool found;
+  long id_tofind;
+  struct connectdata *found;
 };
 
 static int conn_is_conn(struct connectdata *conn, void *param)
 {
   struct connfind *f = (struct connfind *)param;
-  if(conn == f->tofind) {
-    f->found = TRUE;
+  if(conn->connection_id == f->id_tofind) {
+    f->found = conn;
     return 1;
   }
   return 0;
@@ -1393,21 +1393,22 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
    * - that is associated with a multi handle, and whose connection
    *   was detached with CURLOPT_CONNECT_ONLY
    */
-  if(data->state.lastconnect && (data->multi_easy || data->multi)) {
-    struct connectdata *c = data->state.lastconnect;
+  if((data->state.lastconnect_id != -1) && (data->multi_easy || data->multi)) {
+    struct connectdata *c;
     struct connfind find;
-    find.tofind = data->state.lastconnect;
-    find.found = FALSE;
+    find.id_tofind = data->state.lastconnect_id;
+    find.found = NULL;
 
     Curl_conncache_foreach(data, data->multi_easy?
                            &data->multi_easy->conn_cache:
                            &data->multi->conn_cache, &find, conn_is_conn);
 
     if(!find.found) {
-      data->state.lastconnect = NULL;
+      data->state.lastconnect_id = -1;
       return CURL_SOCKET_BAD;
     }
 
+    c = find.found;
     if(connp) {
       /* only store this if the caller cares for it */
       *connp = c;
diff --git a/lib/content_encoding.c b/lib/content_encoding.c
index e2e68a1..2fc3d43 100644
--- a/lib/content_encoding.c
+++ b/lib/content_encoding.c
@@ -38,6 +38,10 @@
 #include <brotli/decode.h>
 #endif
 
+#ifdef HAVE_ZSTD
+#include <zstd.h>
+#endif
+
 #include "sendf.h"
 #include "http.h"
 #include "content_encoding.h"
@@ -710,6 +714,95 @@ static const struct content_encoding brotli_encoding = {
 #endif
 
 
+#ifdef HAVE_ZSTD
+/* Writer parameters. */
+struct zstd_params {
+  ZSTD_DStream *zds;    /* State structure for zstd. */
+  void *decomp;
+};
+
+static CURLcode zstd_init_writer(struct connectdata *conn,
+                                 struct contenc_writer *writer)
+{
+  struct zstd_params *zp = (struct zstd_params *)&writer->params;
+  (void)conn;
+
+  if(!writer->downstream)
+    return CURLE_WRITE_ERROR;
+
+  zp->zds = ZSTD_createDStream();
+  zp->decomp = NULL;
+  return zp->zds ? CURLE_OK : CURLE_OUT_OF_MEMORY;
+}
+
+static CURLcode zstd_unencode_write(struct connectdata *conn,
+    struct contenc_writer *writer,
+    const char *buf, size_t nbytes)
+{
+  CURLcode result = CURLE_OK;
+  struct zstd_params *zp = (struct zstd_params *)&writer->params;
+  ZSTD_inBuffer in;
+  ZSTD_outBuffer out;
+  size_t errorCode;
+
+  if(!zp->decomp) {
+    zp->decomp = malloc(DSIZ);
+    if(!zp->decomp)
+      return CURLE_OUT_OF_MEMORY;
+  }
+  in.pos = 0;
+  in.src = buf;
+  in.size = nbytes;
+
+  for(;;) {
+    out.pos = 0;
+    out.dst = zp->decomp;
+    out.size = DSIZ;
+
+    errorCode = ZSTD_decompressStream(zp->zds, &out, &in);
+    if(ZSTD_isError(errorCode)) {
+      return CURLE_BAD_CONTENT_ENCODING;
+    }
+    if(out.pos > 0) {
+      result = Curl_unencode_write(conn, writer->downstream,
+                                   zp->decomp, out.pos);
+      if(result)
+        break;
+    }
+    if((in.pos == nbytes) && (out.pos < out.size))
+      break;
+  }
+
+  return result;
+}
+
+static void zstd_close_writer(struct connectdata *conn,
+    struct contenc_writer *writer)
+{
+  struct zstd_params *zp = (struct zstd_params *)&writer->params;
+  (void)conn;
+
+  if(zp->decomp) {
+    free(zp->decomp);
+    zp->decomp = NULL;
+  }
+  if(zp->zds) {
+    ZSTD_freeDStream(zp->zds);
+    zp->zds = NULL;
+  }
+}
+
+static const struct content_encoding zstd_encoding = {
+  "zstd",
+  NULL,
+  zstd_init_writer,
+  zstd_unencode_write,
+  zstd_close_writer,
+  sizeof(struct zstd_params)
+};
+#endif
+
+
 /* Identity handler. */
 static CURLcode identity_init_writer(struct connectdata *conn,
                                      struct contenc_writer *writer)
@@ -752,6 +845,9 @@ static const struct content_encoding * const encodings[] = {
 #ifdef HAVE_BROTLI
   &brotli_encoding,
 #endif
+#ifdef HAVE_ZSTD
+  &zstd_encoding,
+#endif
   NULL
 };
 
diff --git a/lib/curl_config.h.cmake b/lib/curl_config.h.cmake
index 05a5acb..dd87078 100644
--- a/lib/curl_config.h.cmake
+++ b/lib/curl_config.h.cmake
@@ -437,6 +437,9 @@
 /* if brotli is available */
 #cmakedefine HAVE_BROTLI 1
 
+/* if zstd is available */
+#cmakedefine HAVE_ZSTD 1
+
 /* if your compiler supports LL */
 #cmakedefine HAVE_LL 1
 
diff --git a/lib/curl_setup.h b/lib/curl_setup.h
index d76c630..21c3f34 100644
--- a/lib/curl_setup.h
+++ b/lib/curl_setup.h
@@ -641,7 +641,7 @@ int netware_init(void);
   defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_SECTRANSP) ||  \
   defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) ||              \
   defined(USE_MBEDTLS) ||                                               \
-  (defined(USE_WOLFSSL) && defined(HAVE_WOLFSSL_DES_SET_ODD_PARITY))
+  (defined(USE_WOLFSSL) && defined(HAVE_WOLFSSL_DES_ECB_ENCRYPT))
 
 #define USE_NTLM
 
diff --git a/lib/curl_sspi.c b/lib/curl_sspi.c
index 83ece9a..512ce24 100644
--- a/lib/curl_sspi.c
+++ b/lib/curl_sspi.c
@@ -28,6 +28,7 @@
 #include "curl_sspi.h"
 #include "curl_multibyte.h"
 #include "system_win32.h"
+#include "version_win32.h"
 #include "warnless.h"
 
 /* The last #include files should be: */
@@ -82,7 +83,7 @@ CURLcode Curl_sspi_global_init(void)
      * have both these DLLs (security.dll forwards calls to secur32.dll) */
 
     /* Load SSPI dll into the address space of the calling process */
-    if(Curl_verify_windows_version(4, 0, PLATFORM_WINNT, VERSION_EQUAL))
+    if(curlx_verify_windows_version(4, 0, PLATFORM_WINNT, VERSION_EQUAL))
       s_hSecDll = Curl_load_library(TEXT("security.dll"));
     else
       s_hSecDll = Curl_load_library(TEXT("secur32.dll"));
diff --git a/lib/curlx.h b/lib/curlx.h
index a8bae14..98e51bf 100644
--- a/lib/curlx.h
+++ b/lib/curlx.h
@@ -63,6 +63,9 @@
   curlx_unicodefree()
 */
 
+#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
diff --git a/lib/doh.c b/lib/doh.c
index ebb2c24..8bc3428 100644
--- a/lib/doh.c
+++ b/lib/doh.c
@@ -858,7 +858,7 @@ doh2ai(const struct dohentry *de, const char *hostname, int port)
       addr = (void *)ai->ai_addr; /* storage area for this info */
       DEBUGASSERT(sizeof(struct in_addr) == sizeof(de->addr[i].ip.v4));
       memcpy(&addr->sin_addr, &de->addr[i].ip.v4, sizeof(struct in_addr));
-      addr->sin_family = (CURL_SA_FAMILY_T)addrtype;
+      addr->sin_family = addrtype;
       addr->sin_port = htons((unsigned short)port);
       break;
 
@@ -867,7 +867,7 @@ doh2ai(const struct dohentry *de, const char *hostname, int port)
       addr6 = (void *)ai->ai_addr; /* storage area for this info */
       DEBUGASSERT(sizeof(struct in6_addr) == sizeof(de->addr[i].ip.v6));
       memcpy(&addr6->sin6_addr, &de->addr[i].ip.v6, sizeof(struct in6_addr));
-      addr6->sin6_family = (CURL_SA_FAMILY_T)addrtype;
+      addr6->sin6_family = addrtype;
       addr6->sin6_port = htons((unsigned short)port);
       break;
 #endif
diff --git a/lib/dynbuf.h b/lib/dynbuf.h
index c80239e..ecc9957 100644
--- a/lib/dynbuf.h
+++ b/lib/dynbuf.h
@@ -53,11 +53,11 @@ size_t Curl_dyn_len(const struct dynbuf *s);
 #define DYN_HAXPROXY        2048
 #define DYN_HTTP_REQUEST    (128*1024)
 #define DYN_H2_HEADERS      (128*1024)
-#define DYN_H2_TRAILER      4096
+#define DYN_H2_TRAILERS     (128*1024)
 #define DYN_APRINTF         8000000
 #define DYN_RTSP_REQ_HEADER (64*1024)
 #define DYN_TRAILERS        (64*1024)
 #define DYN_PROXY_CONNECT_HEADERS 16384
 #define DYN_QLOG_NAME       1024
-#define DYN_H1_TRAILER      DYN_H2_TRAILER
+#define DYN_H1_TRAILER      4096
 #endif
diff --git a/lib/easy.c b/lib/easy.c
index 292cca7..a69eb9e 100644
--- a/lib/easy.c
+++ b/lib/easy.c
@@ -838,8 +838,7 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
 
   /* the connection cache is setup on demand */
   outcurl->state.conn_cache = NULL;
-
-  outcurl->state.lastconnect = NULL;
+  outcurl->state.lastconnect_id = -1;
 
   outcurl->progress.flags    = data->progress.flags;
   outcurl->progress.callback = data->progress.callback;
diff --git a/lib/ftp.c b/lib/ftp.c
index 20351ff..9fadac5 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -3251,9 +3251,9 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
     }
 
     if(conn->ssl[SECONDARYSOCKET].use) {
-      /* The secondary socket used SSL so we must close down that part first
-         before we close the socket for real */
-      result = Curl_ssl_shutdown(conn, SECONDARYSOCKET);
+      /* The secondary socket is using SSL so we must close down that part
+         first before we close the socket for real */
+      Curl_ssl_close(conn, SECONDARYSOCKET);
 
       /* Note that we keep "use" set to TRUE since that (next) connection is
          still requested to use SSL */
diff --git a/lib/getinfo.c b/lib/getinfo.c
index 6d5bd5f..82691dc 100644
--- a/lib/getinfo.c
+++ b/lib/getinfo.c
@@ -78,6 +78,7 @@ CURLcode Curl_initinfo(struct Curl_easy *data)
   info->conn_local_ip[0] = '\0';
   info->conn_primary_port = 0;
   info->conn_local_port = 0;
+  info->retry_after = 0;
 
   info->conn_scheme = 0;
   info->conn_protocol = 0;
@@ -95,6 +96,34 @@ static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info,
   case CURLINFO_EFFECTIVE_URL:
     *param_charp = data->change.url?data->change.url:(char *)"";
     break;
+  case CURLINFO_EFFECTIVE_METHOD: {
+    const char *m = data->set.str[STRING_CUSTOMREQUEST];
+    if(!m) {
+      if(data->set.opt_no_body)
+        m = "HEAD";
+      else {
+        switch(data->state.httpreq) {
+        case HTTPREQ_POST:
+        case HTTPREQ_POST_FORM:
+        case HTTPREQ_POST_MIME:
+          m = "POST";
+          break;
+        case HTTPREQ_PUT:
+          m = "PUT";
+          break;
+        default: /* this should never happen */
+        case HTTPREQ_GET:
+          m = "GET";
+          break;
+        case HTTPREQ_HEAD:
+          m = "HEAD";
+          break;
+        }
+      }
+    }
+    *param_charp = m;
+  }
+    break;
   case CURLINFO_CONTENT_TYPE:
     *param_charp = data->info.contenttype;
     break;
diff --git a/lib/http.c b/lib/http.c
index 28d66c2..8fcdd43 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -2014,9 +2014,6 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
       case HTTPREQ_PUT:
         request = "PUT";
         break;
-      case HTTPREQ_OPTIONS:
-        request = "OPTIONS";
-        break;
       default: /* this should never happen */
       case HTTPREQ_GET:
         request = "GET";
diff --git a/lib/http.h b/lib/http.h
index 641bc0b..9ea3eb2 100644
--- a/lib/http.h
+++ b/lib/http.h
@@ -148,6 +148,7 @@ struct HTTP {
   struct dynbuf header_recvbuf;
   size_t nread_header_recvbuf; /* number of bytes in header_recvbuf fed into
                                   upper layer */
+  struct dynbuf trailer_recvbuf;
   int status_code; /* HTTP status code */
   const uint8_t *pausedata; /* pointer to data received in on_data_chunk */
   size_t pauselen; /* the number of bytes left in data */
diff --git a/lib/http2.c b/lib/http2.c
index 6cf651f..d316da8 100644
--- a/lib/http2.c
+++ b/lib/http2.c
@@ -514,7 +514,7 @@ static int push_promise(struct Curl_easy *data,
                         struct connectdata *conn,
                         const nghttp2_push_promise *frame)
 {
-  int rv;
+  int rv; /* one of the CURL_PUSH_* defines */
   H2BUGF(infof(data, "PUSH_PROMISE received, stream %u!\n",
                frame->promised_stream_id));
   if(data->multi->push_cb) {
@@ -528,7 +528,7 @@ static int push_promise(struct Curl_easy *data,
     struct Curl_easy *newhandle = duphandle(data);
     if(!newhandle) {
       infof(data, "failed to duplicate handle\n");
-      rv = 1; /* FAIL HARD */
+      rv = CURL_PUSH_DENY; /* FAIL HARD */
       goto fail;
     }
 
@@ -541,13 +541,15 @@ static int push_promise(struct Curl_easy *data,
     if(!stream) {
       failf(data, "Internal NULL stream!\n");
       (void)Curl_close(&newhandle);
-      rv = 1;
+      rv = CURL_PUSH_DENY;
       goto fail;
     }
 
     rv = set_transfer_url(newhandle, &heads);
-    if(rv)
+    if(rv) {
+      rv = CURL_PUSH_DENY;
       goto fail;
+    }
 
     Curl_set_in_callback(data, true);
     rv = data->multi->push_cb(data, newhandle,
@@ -563,6 +565,7 @@ static int push_promise(struct Curl_easy *data,
     stream->push_headers_used = 0;
 
     if(rv) {
+      DEBUGASSERT((rv > CURL_PUSH_OK) && (rv <= CURL_PUSH_ERROROUT));
       /* denied, kill off the new handle again */
       http2_stream_free(newhandle->req.protop);
       newhandle->req.protop = NULL;
@@ -583,7 +586,7 @@ static int push_promise(struct Curl_easy *data,
       http2_stream_free(newhandle->req.protop);
       newhandle->req.protop = NULL;
       Curl_close(&newhandle);
-      rv = 1;
+      rv = CURL_PUSH_DENY;
       goto fail;
     }
 
@@ -595,12 +598,13 @@ static int push_promise(struct Curl_easy *data,
       infof(data, "failed to set user_data for stream %d\n",
             frame->promised_stream_id);
       DEBUGASSERT(0);
+      rv = CURL_PUSH_DENY;
       goto fail;
     }
   }
   else {
     H2BUGF(infof(data, "Got PUSH_PROMISE, ignore it!\n"));
-    rv = 1;
+    rv = CURL_PUSH_DENY;
   }
   fail:
   return rv;
@@ -737,11 +741,16 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
   case NGHTTP2_PUSH_PROMISE:
     rv = push_promise(data_s, conn, &frame->push_promise);
     if(rv) { /* deny! */
-      rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
+      int h2;
+      DEBUGASSERT((rv > CURL_PUSH_OK) && (rv <= CURL_PUSH_ERROROUT));
+      h2 = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
                                      frame->push_promise.promised_stream_id,
                                      NGHTTP2_CANCEL);
-      if(nghttp2_is_fatal(rv)) {
-        return rv;
+      if(nghttp2_is_fatal(h2))
+        return NGHTTP2_ERR_CALLBACK_FAILURE;
+      else if(rv == CURL_PUSH_ERROROUT) {
+        DEBUGF(infof(data_s, "Fail the parent stream (too)\n"));
+        return NGHTTP2_ERR_CALLBACK_FAILURE;
       }
     }
     break;
@@ -839,7 +848,7 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
       return 0;
     }
     H2BUGF(infof(data_s, "on_stream_close(), %s (err %d), stream %u\n",
-                 nghttp2_strerror(error_code), error_code, stream_id));
+                 nghttp2_http2_strerror(error_code), error_code, stream_id));
     stream = data_s->req.protop;
     if(!stream)
       return NGHTTP2_ERR_CALLBACK_FAILURE;
@@ -1006,18 +1015,11 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
 
   if(stream->bodystarted) {
     /* This is a trailer */
-    struct dynbuf trail;
     H2BUGF(infof(data_s, "h2 trailer: %.*s: %.*s\n", namelen, name, valuelen,
                  value));
-    Curl_dyn_init(&trail, DYN_H2_TRAILER);
-    result = Curl_dyn_addf(&trail,
+    result = Curl_dyn_addf(&stream->trailer_recvbuf,
                            "%.*s: %.*s\r\n", namelen, name,
                            valuelen, value);
-    if(!result)
-      result = Curl_client_write(conn, CLIENTWRITE_HEADER,
-                                 Curl_dyn_ptr(&trail),
-                                 Curl_dyn_len(&trail));
-    Curl_dyn_free(&trail);
     if(result)
       return NGHTTP2_ERR_CALLBACK_FAILURE;
 
@@ -1165,6 +1167,7 @@ void Curl_http2_done(struct Curl_easy *data, bool premature)
   /* there might be allocated resources done before this got the 'h2' pointer
      setup */
   Curl_dyn_free(&http->header_recvbuf);
+  Curl_dyn_free(&http->trailer_recvbuf);
   if(http->push_headers) {
     /* if they weren't used and then freed before */
     for(; http->push_headers_used > 0; --http->push_headers_used) {
@@ -1174,7 +1177,8 @@ void Curl_http2_done(struct Curl_easy *data, bool premature)
     http->push_headers = NULL;
   }
 
-  if(!httpc->h2) /* not HTTP/2 ? */
+  if(!(data->conn->handler->protocol&PROTO_FAMILY_HTTP) ||
+     !httpc->h2) /* not HTTP/2 ? */
     return;
 
   if(premature) {
@@ -1203,6 +1207,13 @@ void Curl_http2_done(struct Curl_easy *data, bool premature)
     }
     http->stream_id = 0;
   }
+
+  if(0 == nghttp2_session_check_request_allowed(httpc->h2)) {
+    /* No more requests are allowed in the current session, so the connection
+       may not be reused. This is set when a GOAWAY frame has been received or
+       when the limit of stream identifiers has been reached. */
+    connclose(data->conn, "http/2: No new requests allowed");
+  }
 }
 
 /*
@@ -1456,7 +1467,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
   }
   else if(httpc->error_code != NGHTTP2_NO_ERROR) {
     failf(data, "HTTP/2 stream %d was not closed cleanly: %s (err %u)",
-          stream->stream_id, nghttp2_strerror(httpc->error_code),
+          stream->stream_id, nghttp2_http2_strerror(httpc->error_code),
           httpc->error_code);
     *err = CURLE_HTTP2_STREAM;
     return -1;
@@ -1470,6 +1481,31 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
     return -1;
   }
 
+  if(Curl_dyn_len(&stream->trailer_recvbuf)) {
+    char *trailp = Curl_dyn_ptr(&stream->trailer_recvbuf);
+    char *lf;
+
+    do {
+      size_t len = 0;
+      CURLcode result;
+      /* each trailer line ends with a newline */
+      lf = strchr(trailp, '\n');
+      if(!lf)
+        break;
+      len = lf + 1 - trailp;
+
+      if(data->set.verbose)
+        Curl_debug(data, CURLINFO_HEADER_IN, trailp, len);
+      /* pass the trailers one by one to the callback */
+      result = Curl_client_write(conn, CLIENTWRITE_HEADER, trailp, len);
+      if(result) {
+        *err = result;
+        return -1;
+      }
+      trailp = ++lf;
+    } while(lf);
+  }
+
   stream->close_handled = TRUE;
 
   H2BUGF(infof(data, "http2_recv returns 0, http2_handle_stream_close\n"));
@@ -2075,6 +2111,9 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
 
   h2_pri_spec(conn->data, &pri_spec);
 
+  H2BUGF(infof(conn->data, "http2_send request allowed %d (easy handle %p)\n",
+               nghttp2_session_check_request_allowed(h2), (void *)conn->data));
+
   switch(conn->data->state.httpreq) {
   case HTTPREQ_POST:
   case HTTPREQ_POST_FORM:
@@ -2151,6 +2190,7 @@ CURLcode Curl_http2_setup(struct connectdata *conn)
   stream->stream_id = -1;
 
   Curl_dyn_init(&stream->header_recvbuf, DYN_H2_HEADERS);
+  Curl_dyn_init(&stream->trailer_recvbuf, DYN_H2_TRAILERS);
 
   if((conn->handler == &Curl_handler_http2_ssl) ||
      (conn->handler == &Curl_handler_http2))
diff --git a/lib/md4.c b/lib/md4.c
index 0fab52d..67119cd 100644
--- a/lib/md4.c
+++ b/lib/md4.c
@@ -102,7 +102,9 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
 #include <openssl/md4.h>
 
 #elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
-              (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040)) || \
+              (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040) && \
+       defined(__MAC_OS_X_VERSION_MIN_ALLOWED) && \
+              (__MAC_OS_X_VERSION_MIN_ALLOWED < 101500)) || \
       (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
               (__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000))
 
diff --git a/lib/md5.c b/lib/md5.c
index 557a51e..d21625f 100644
--- a/lib/md5.c
+++ b/lib/md5.c
@@ -139,7 +139,9 @@ static void MD5_Final(unsigned char *digest, MD5_CTX *ctx)
 }
 
 #elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
-              (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040)) || \
+              (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040) && \
+       defined(__MAC_OS_X_VERSION_MIN_ALLOWED) && \
+              (__MAC_OS_X_VERSION_MIN_ALLOWED < 101500)) || \
       (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
               (__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000))
 
diff --git a/lib/memdebug.c b/lib/memdebug.c
index 1c6b151..da75c9f 100644
--- a/lib/memdebug.c
+++ b/lib/memdebug.c
@@ -456,6 +456,16 @@ FILE *curl_dbg_fopen(const char *file, const char *mode,
   return res;
 }
 
+FILE *curl_dbg_fdopen(int filedes, const char *mode,
+                      int line, const char *source)
+{
+  FILE *res = fdopen(filedes, mode);
+  if(source)
+    curl_dbg_log("FILE %s:%d fdopen(\"%d\",\"%s\") = %p\n",
+                 source, line, filedes, mode, (void *)res);
+  return res;
+}
+
 int curl_dbg_fclose(FILE *file, int line, const char *source)
 {
   int res;
diff --git a/lib/memdebug.h b/lib/memdebug.h
index 7ca4426..4edafdf 100644
--- a/lib/memdebug.h
+++ b/lib/memdebug.h
@@ -8,7 +8,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -79,6 +79,9 @@ CURL_EXTERN RECV_TYPE_RETV curl_dbg_recv(RECV_TYPE_ARG1 sockfd,
 /* FILE functions */
 CURL_EXTERN FILE *curl_dbg_fopen(const char *file, const char *mode, int line,
                                  const char *source);
+CURL_EXTERN FILE *curl_dbg_fdopen(int filedes, const char *mode,
+                                  int line, const char *source);
+
 CURL_EXTERN int curl_dbg_fclose(FILE *file, int line, const char *source);
 
 #ifndef MEMDEBUG_NODEFINES
diff --git a/lib/mprintf.c b/lib/mprintf.c
index 63c9d11..80735be 100644
--- a/lib/mprintf.c
+++ b/lib/mprintf.c
@@ -178,12 +178,14 @@ static long dprintf_DollarString(char *input, char **end)
 {
   int number = 0;
   while(ISDIGIT(*input)) {
-    number *= 10;
-    number += *input-'0';
+    if(number < MAX_PARAMETERS) {
+      number *= 10;
+      number += *input - '0';
+    }
     input++;
   }
-  if(number && ('$'==*input++)) {
-    *end = input;
+  if(number <= MAX_PARAMETERS && ('$' == *input)) {
+    *end = ++input;
     return number;
   }
   return 0;
@@ -377,6 +379,8 @@ static int dprintf_Pass1(const char *format, struct va_stack *vto,
           if(width > max_param)
             max_param = width;
           break;
+        case '\0':
+          fmt--;
         default:
           break;
         }
@@ -458,6 +462,9 @@ static int dprintf_Pass1(const char *format, struct va_stack *vto,
         /* we have the width specified from a parameter, so we make that
            parameter's info setup properly */
         long k = width - 1;
+        if((k < 0) || (k >= MAX_PARAMETERS))
+          /* out of allowed range */
+          return 1;
         vto[i].width = k;
         vto[k].type = FORMAT_WIDTH;
         vto[k].flags = FLAGS_NEW;
@@ -469,6 +476,9 @@ static int dprintf_Pass1(const char *format, struct va_stack *vto,
         /* we have the precision specified from a parameter, so we make that
            parameter's info setup properly */
         long k = precision - 1;
+        if((k < 0) || (k >= MAX_PARAMETERS))
+          /* out of allowed range */
+          return 1;
         vto[i].precision = k;
         vto[k].type = FORMAT_WIDTH;
         vto[k].flags = FLAGS_NEW;
@@ -476,7 +486,7 @@ static int dprintf_Pass1(const char *format, struct va_stack *vto,
         vto[k].width = 0;
         vto[k].precision = 0;
       }
-      *endpos++ = fmt + 1; /* end of this sequence */
+      *endpos++ = fmt + ((*fmt == '\0') ? 0 : 1); /* end of this sequence */
     }
   }
 
@@ -754,7 +764,7 @@ static int dprintf_formatf(
 
       if(prec > 0) {
         width -= prec;
-        while(prec-- > 0)
+        while(prec-- > 0 && w >= work)
           *w-- = '0';
       }
 
@@ -918,6 +928,8 @@ static int dprintf_formatf(
              precision */
           size_t maxprec = sizeof(work) - 2;
           double val = p->data.dnum;
+          if(width > 0 && prec <= width)
+            maxprec -= width;
           while(val >= 10.0) {
             val /= 10;
             maxprec--;
@@ -925,6 +937,8 @@ static int dprintf_formatf(
 
           if(prec > (long)maxprec)
             prec = (long)maxprec-1;
+          if(prec < 0)
+            prec = 0;
           /* RECURSIVE USAGE */
           len = curl_msnprintf(fptr, left, ".%ld", prec);
           fptr += len;
diff --git a/lib/multi.c b/lib/multi.c
index 249e360..3c7fb85 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -455,6 +455,7 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
     data->state.conn_cache = &data->share->conn_cache;
   else
     data->state.conn_cache = &multi->conn_cache;
+  data->state.lastconnect_id = -1;
 
 #ifdef USE_LIBPSL
   /* Do the same for PSL. */
@@ -677,11 +678,11 @@ static CURLcode multi_done(struct Curl_easy *data,
     CONNCACHE_UNLOCK(data);
     if(Curl_conncache_return_conn(data, conn)) {
       /* remember the most recently used connection */
-      data->state.lastconnect = conn;
+      data->state.lastconnect_id = conn->connection_id;
       infof(data, "%s\n", buffer);
     }
     else
-      data->state.lastconnect = NULL;
+      data->state.lastconnect_id = -1;
   }
 
   Curl_safefree(data->state.buffer);
@@ -689,6 +690,26 @@ static CURLcode multi_done(struct Curl_easy *data,
   return result;
 }
 
+static int close_connect_only(struct connectdata *conn, void *param)
+{
+  struct Curl_easy *data = param;
+
+  if(data->state.lastconnect_id != conn->connection_id)
+    return 0;
+
+  if(conn->data != data)
+    return 1;
+  conn->data = NULL;
+
+  if(!conn->bits.connect_only)
+    return 1;
+
+  connclose(conn, "Removing connect-only easy handle");
+  conn->bits.connect_only = FALSE;
+
+  return 1;
+}
+
 CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
                                    struct Curl_easy *data)
 {
@@ -776,10 +797,6 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
      multi_done() as that may actually call Curl_expire that uses this */
   Curl_llist_destroy(&data->state.timeoutlist, NULL);
 
-  /* as this was using a shared connection cache we clear the pointer to that
-     since we're not part of that multi handle anymore */
-  data->state.conn_cache = NULL;
-
   /* change state without using multistate(), only to make singlesocket() do
      what we want */
   data->mstate = CURLM_STATE_COMPLETED;
@@ -789,12 +806,22 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
   /* Remove the association between the connection and the handle */
   Curl_detach_connnection(data);
 
+  if(data->state.lastconnect_id != -1) {
+    /* Mark any connect-only connection for closure */
+    Curl_conncache_foreach(data, data->state.conn_cache,
+                           data, &close_connect_only);
+  }
+
 #ifdef USE_LIBPSL
   /* Remove the PSL association. */
   if(data->psl == &multi->psl)
     data->psl = NULL;
 #endif
 
+  /* as this was using a shared connection cache we clear the pointer to that
+     since we're not part of that multi handle anymore */
+  data->state.conn_cache = NULL;
+
   data->multi = NULL; /* clear the association to this multi handle */
 
   /* make sure there's no pending message in the queue sent from this easy
@@ -958,19 +985,6 @@ static int multi_getsock(struct Curl_easy *data,
 
   switch(data->mstate) {
   default:
-#if 0 /* switch back on these cases to get the compiler to check for all enums
-         to be present */
-  case CURLM_STATE_TOOFAST:  /* returns 0, so will not select. */
-  case CURLM_STATE_COMPLETED:
-  case CURLM_STATE_MSGSENT:
-  case CURLM_STATE_INIT:
-  case CURLM_STATE_CONNECT:
-  case CURLM_STATE_WAITDO:
-  case CURLM_STATE_DONE:
-  case CURLM_STATE_LAST:
-    /* this will get called with CURLM_STATE_COMPLETED when a handle is
-       removed */
-#endif
     return 0;
 
   case CURLM_STATE_WAITRESOLVE:
@@ -1255,7 +1269,7 @@ static CURLMcode Curl_multi_wait(struct Curl_multi *multi,
         sleep_ms = timeout_ms;
       /* when there are no easy handles in the multi, this holds a -1
          timeout */
-      else if((sleep_ms < 0) && extrawait)
+      else if(sleep_ms < 0)
         sleep_ms = timeout_ms;
       Curl_wait_ms(sleep_ms);
     }
@@ -1808,7 +1822,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
             multistate(data, CURLM_STATE_SENDPROTOCONNECT);
           }
         }
-      else if(result)
+      else
         stream_error = TRUE;
       break;
 #endif
@@ -1858,7 +1872,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
         multistate(data, CURLM_STATE_DO);
         rc = CURLM_CALL_MULTI_PERFORM;
       }
-      else if(result) {
+      else {
         /* failure detected */
         Curl_posttransfer(data);
         multi_done(data, result, TRUE);
@@ -2962,9 +2976,7 @@ CURLMcode curl_multi_setopt(struct Curl_multi *multi,
       long streams = va_arg(param, long);
       if(streams < 1)
         streams = 100;
-      multi->max_concurrent_streams =
-        (streams > (long)INITIAL_MAX_CONCURRENT_STREAMS)?
-        INITIAL_MAX_CONCURRENT_STREAMS : (unsigned int)streams;
+      multi->max_concurrent_streams = curlx_sltoui(streams);
     }
     break;
   default:
diff --git a/lib/multihandle.h b/lib/multihandle.h
index 91eca16..9d73df0 100644
--- a/lib/multihandle.h
+++ b/lib/multihandle.h
@@ -81,7 +81,7 @@ struct Curl_multi {
      this multi handle with an easy handle. Set this to CURL_MULTI_HANDLE. */
   long type;
 
-  /* We have a doubly-linked circular list with easy handles */
+  /* We have a doubly-linked list with easy handles */
   struct Curl_easy *easyp;
   struct Curl_easy *easylp; /* last node */
 
diff --git a/lib/parsedate.c b/lib/parsedate.c
index 585d7ea..4c7a40c 100644
--- a/lib/parsedate.c
+++ b/lib/parsedate.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -624,6 +624,7 @@ CURLcode Curl_gmtime(time_t intime, struct tm *store)
   /* thread-safe version */
   tm = (struct tm *)gmtime_r(&intime, store);
 #else
+  /* !checksrc! disable BANNEDFUNC 1 */
   tm = gmtime(&intime);
   if(tm)
     *store = *tm; /* copy the pointed struct to the local copy */
diff --git a/lib/rename.c b/lib/rename.c
index bb170d3..fe5f95d 100644
--- a/lib/rename.c
+++ b/lib/rename.c
@@ -27,6 +27,7 @@
 #if (!defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)) ||  \
   defined(USE_ALTSVC)
 
+#include "curl_multibyte.h"
 #include "timeval.h"
 
 /* The last 3 #include files should be in this order */
@@ -39,17 +40,25 @@ int Curl_rename(const char *oldpath, const char *newpath)
 {
 #ifdef WIN32
   /* rename() on Windows doesn't overwrite, so we can't use it here.
-     MoveFileExA() will overwrite and is usually atomic, however it fails
+     MoveFileEx() will overwrite and is usually atomic, however it fails
      when there are open handles to the file. */
   const int max_wait_ms = 1000;
   struct curltime start = Curl_now();
+  TCHAR *tchar_oldpath = curlx_convert_UTF8_to_tchar((char *)oldpath);
+  TCHAR *tchar_newpath = curlx_convert_UTF8_to_tchar((char *)newpath);
   for(;;) {
     timediff_t diff;
-    if(MoveFileExA(oldpath, newpath, MOVEFILE_REPLACE_EXISTING))
+    if(MoveFileEx(tchar_oldpath, tchar_newpath, MOVEFILE_REPLACE_EXISTING)) {
+      curlx_unicodefree(tchar_oldpath);
+      curlx_unicodefree(tchar_newpath);
       break;
+    }
     diff = Curl_timediff(Curl_now(), start);
-    if(diff < 0 || diff > max_wait_ms)
+    if(diff < 0 || diff > max_wait_ms) {
+      curlx_unicodefree(tchar_oldpath);
+      curlx_unicodefree(tchar_newpath);
       return 1;
+    }
     Sleep(1);
   }
 #else
diff --git a/lib/setopt.c b/lib/setopt.c
index 90edf6a..d621335 100644
--- a/lib/setopt.c
+++ b/lib/setopt.c
@@ -274,6 +274,8 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
     if(data->set.opt_no_body)
       /* in HTTP lingo, no body means using the HEAD request... */
       data->set.method = HTTPREQ_HEAD;
+    else if(data->set.method == HTTPREQ_HEAD)
+      data->set.method = HTTPREQ_GET;
     break;
   case CURLOPT_FAILONERROR:
     /*
diff --git a/lib/smtp.c b/lib/smtp.c
index 685513b..aea41bb 100644
--- a/lib/smtp.c
+++ b/lib/smtp.c
@@ -1760,8 +1760,10 @@ static CURLcode smtp_parse_address(struct connectdata *conn, const char *fqma,
     return CURLE_OUT_OF_MEMORY;
 
   length = strlen(dup);
-  if(dup[length - 1] == '>')
-    dup[length - 1] = '\0';
+  if(length) {
+    if(dup[length - 1] == '>')
+      dup[length - 1] = '\0';
+  }
 
   /* Extract the host name from the address (if we can) */
   host->name = strpbrk(dup, "@");
diff --git a/lib/socks.c b/lib/socks.c
index b2215fe..44783d0 100644
--- a/lib/socks.c
+++ b/lib/socks.c
@@ -327,18 +327,18 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
      * Make connection
      */
     {
-      ssize_t packetsize = 9 +
+      size_t packetsize = 9 +
         strlen((char *)socksreq + 8); /* size including NUL */
 
       /* If SOCKS4a, set special invalid IP address 0.0.0.x */
       if(protocol4a) {
-        ssize_t hostnamelen = 0;
+        size_t hostnamelen = 0;
         socksreq[4] = 0;
         socksreq[5] = 0;
         socksreq[6] = 0;
         socksreq[7] = 1;
         /* append hostname */
-        hostnamelen = (ssize_t)strlen(hostname) + 1; /* length including NUL */
+        hostnamelen = strlen(hostname) + 1; /* length including NUL */
         if(hostnamelen <= 255)
           strcpy((char *)socksreq + packetsize, hostname);
         else {
diff --git a/lib/strdup.c b/lib/strdup.c
index 1ab10fd..7732802 100644
--- a/lib/strdup.c
+++ b/lib/strdup.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -39,19 +39,14 @@ char *curlx_strdup(const char *str)
   if(!str)
     return (char *)NULL;
 
-  len = strlen(str);
+  len = strlen(str) + 1;
 
-  if(len >= ((size_t)-1) / sizeof(char))
-    return (char *)NULL;
-
-  newstr = malloc((len + 1)*sizeof(char));
+  newstr = malloc(len);
   if(!newstr)
     return (char *)NULL;
 
-  memcpy(newstr, str, (len + 1)*sizeof(char));
-
+  memcpy(newstr, str, len);
   return newstr;
-
 }
 #endif
 
diff --git a/lib/system_win32.c b/lib/system_win32.c
index b9587b5..2e59e03 100644
--- a/lib/system_win32.c
+++ b/lib/system_win32.c
@@ -26,6 +26,7 @@
 
 #include <curl/curl.h>
 #include "system_win32.h"
+#include "version_win32.h"
 #include "curl_sspi.h"
 #include "warnless.h"
 
@@ -106,8 +107,8 @@ CURLcode Curl_win32_init(long flags)
       Curl_if_nametoindex = pIfNameToIndex;
   }
 
-  if(Curl_verify_windows_version(6, 0, PLATFORM_WINNT,
-                                 VERSION_GREATER_THAN_EQUAL)) {
+  if(curlx_verify_windows_version(6, 0, PLATFORM_WINNT,
+                                  VERSION_GREATER_THAN_EQUAL)) {
     Curl_isVistaOrGreater = TRUE;
   }
   else
@@ -160,198 +161,6 @@ typedef HMODULE (APIENTRY *LOADLIBRARYEX_FN)(LPCTSTR, HANDLE, DWORD);
 #endif
 
 /*
- * Curl_verify_windows_version()
- *
- * This is used to verify if we are running on a specific windows version.
- *
- * Parameters:
- *
- * majorVersion [in] - The major version number.
- * minorVersion [in] - The minor version number.
- * platform     [in] - The optional platform identifier.
- * condition    [in] - The test condition used to specifier whether we are
- *                     checking a version less then, equal to or greater than
- *                     what is specified in the major and minor version
- *                     numbers.
- *
- * Returns TRUE if matched; otherwise FALSE.
- */
-bool Curl_verify_windows_version(const unsigned int majorVersion,
-                                 const unsigned int minorVersion,
-                                 const PlatformIdentifier platform,
-                                 const VersionCondition condition)
-{
-  bool matched = FALSE;
-
-#if defined(CURL_WINDOWS_APP)
-  /* We have no way to determine the Windows version from Windows apps,
-     so let's assume we're running on the target Windows version. */
-  const WORD fullVersion = MAKEWORD(minorVersion, majorVersion);
-  const WORD targetVersion = (WORD)_WIN32_WINNT;
-
-  switch(condition) {
-  case VERSION_LESS_THAN:
-    matched = targetVersion < fullVersion;
-    break;
-
-  case VERSION_LESS_THAN_EQUAL:
-    matched = targetVersion <= fullVersion;
-    break;
-
-  case VERSION_EQUAL:
-    matched = targetVersion == fullVersion;
-    break;
-
-  case VERSION_GREATER_THAN_EQUAL:
-    matched = targetVersion >= fullVersion;
-    break;
-
-  case VERSION_GREATER_THAN:
-    matched = targetVersion > fullVersion;
-    break;
-  }
-
-  if(matched && (platform == PLATFORM_WINDOWS)) {
-    /* we're always running on PLATFORM_WINNT */
-    matched = FALSE;
-  }
-#elif !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \
-    (_WIN32_WINNT < _WIN32_WINNT_WIN2K)
-  OSVERSIONINFO osver;
-
-  memset(&osver, 0, sizeof(osver));
-  osver.dwOSVersionInfoSize = sizeof(osver);
-
-  /* Find out Windows version */
-  if(GetVersionEx(&osver)) {
-    /* Verify the Operating System version number */
-    switch(condition) {
-    case VERSION_LESS_THAN:
-      if(osver.dwMajorVersion < majorVersion ||
-        (osver.dwMajorVersion == majorVersion &&
-         osver.dwMinorVersion < minorVersion))
-        matched = TRUE;
-      break;
-
-    case VERSION_LESS_THAN_EQUAL:
-      if(osver.dwMajorVersion < majorVersion ||
-        (osver.dwMajorVersion == majorVersion &&
-         osver.dwMinorVersion <= minorVersion))
-        matched = TRUE;
-      break;
-
-    case VERSION_EQUAL:
-      if(osver.dwMajorVersion == majorVersion &&
-         osver.dwMinorVersion == minorVersion)
-        matched = TRUE;
-      break;
-
-    case VERSION_GREATER_THAN_EQUAL:
-      if(osver.dwMajorVersion > majorVersion ||
-        (osver.dwMajorVersion == majorVersion &&
-         osver.dwMinorVersion >= minorVersion))
-        matched = TRUE;
-      break;
-
-    case VERSION_GREATER_THAN:
-      if(osver.dwMajorVersion > majorVersion ||
-        (osver.dwMajorVersion == majorVersion &&
-         osver.dwMinorVersion > minorVersion))
-        matched = TRUE;
-      break;
-    }
-
-    /* Verify the platform identifier (if necessary) */
-    if(matched) {
-      switch(platform) {
-      case PLATFORM_WINDOWS:
-        if(osver.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS)
-          matched = FALSE;
-        break;
-
-      case PLATFORM_WINNT:
-        if(osver.dwPlatformId != VER_PLATFORM_WIN32_NT)
-          matched = FALSE;
-
-      default: /* like platform == PLATFORM_DONT_CARE */
-        break;
-      }
-    }
-  }
-#else
-  ULONGLONG cm = 0;
-  OSVERSIONINFOEX osver;
-  BYTE majorCondition;
-  BYTE minorCondition;
-  BYTE spMajorCondition;
-  BYTE spMinorCondition;
-
-  switch(condition) {
-  case VERSION_LESS_THAN:
-    majorCondition = VER_LESS;
-    minorCondition = VER_LESS;
-    spMajorCondition = VER_LESS_EQUAL;
-    spMinorCondition = VER_LESS_EQUAL;
-    break;
-
-  case VERSION_LESS_THAN_EQUAL:
-    majorCondition = VER_LESS_EQUAL;
-    minorCondition = VER_LESS_EQUAL;
-    spMajorCondition = VER_LESS_EQUAL;
-    spMinorCondition = VER_LESS_EQUAL;
-    break;
-
-  case VERSION_EQUAL:
-    majorCondition = VER_EQUAL;
-    minorCondition = VER_EQUAL;
-    spMajorCondition = VER_GREATER_EQUAL;
-    spMinorCondition = VER_GREATER_EQUAL;
-    break;
-
-  case VERSION_GREATER_THAN_EQUAL:
-    majorCondition = VER_GREATER_EQUAL;
-    minorCondition = VER_GREATER_EQUAL;
-    spMajorCondition = VER_GREATER_EQUAL;
-    spMinorCondition = VER_GREATER_EQUAL;
-    break;
-
-  case VERSION_GREATER_THAN:
-    majorCondition = VER_GREATER;
-    minorCondition = VER_GREATER;
-    spMajorCondition = VER_GREATER_EQUAL;
-    spMinorCondition = VER_GREATER_EQUAL;
-    break;
-
-  default:
-    return FALSE;
-  }
-
-  memset(&osver, 0, sizeof(osver));
-  osver.dwOSVersionInfoSize = sizeof(osver);
-  osver.dwMajorVersion = majorVersion;
-  osver.dwMinorVersion = minorVersion;
-  if(platform == PLATFORM_WINDOWS)
-    osver.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS;
-  else if(platform == PLATFORM_WINNT)
-    osver.dwPlatformId = VER_PLATFORM_WIN32_NT;
-
-  cm = VerSetConditionMask(cm, VER_MAJORVERSION, majorCondition);
-  cm = VerSetConditionMask(cm, VER_MINORVERSION, minorCondition);
-  cm = VerSetConditionMask(cm, VER_SERVICEPACKMAJOR, spMajorCondition);
-  cm = VerSetConditionMask(cm, VER_SERVICEPACKMINOR, spMinorCondition);
-  if(platform != PLATFORM_DONT_CARE)
-    cm = VerSetConditionMask(cm, VER_PLATFORMID, VER_EQUAL);
-
-  if(VerifyVersionInfo(&osver, (VER_MAJORVERSION | VER_MINORVERSION |
-                                VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR),
-                       cm))
-    matched = TRUE;
-#endif
-
-  return matched;
-}
-
-/*
  * Curl_load_library()
  *
  * This is used to dynamically load DLLs using the most secure method available
diff --git a/lib/system_win32.h b/lib/system_win32.h
index d2882fc..2547bda 100644
--- a/lib/system_win32.h
+++ b/lib/system_win32.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2016 - 2019, Steve Holme, <steve_holme@hotmail.com>.
+ * Copyright (C) 2016 - 2020, Steve Holme, <steve_holme@hotmail.com>.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -32,34 +32,12 @@ extern bool Curl_isVistaOrGreater;
 CURLcode Curl_win32_init(long flags);
 void Curl_win32_cleanup(long init_flags);
 
-/* Version condition */
-typedef enum {
-  VERSION_LESS_THAN,
-  VERSION_LESS_THAN_EQUAL,
-  VERSION_EQUAL,
-  VERSION_GREATER_THAN_EQUAL,
-  VERSION_GREATER_THAN
-} VersionCondition;
-
-/* Platform identifier */
-typedef enum {
-  PLATFORM_DONT_CARE,
-  PLATFORM_WINDOWS,
-  PLATFORM_WINNT
-} PlatformIdentifier;
-
 /* We use our own typedef here since some headers might lack this */
 typedef unsigned int(WINAPI *IF_NAMETOINDEX_FN)(const char *);
 
 /* This is used instead of if_nametoindex if available on Windows */
 extern IF_NAMETOINDEX_FN Curl_if_nametoindex;
 
-/* This is used to verify if we are running on a specific windows version */
-bool Curl_verify_windows_version(const unsigned int majorVersion,
-                                 const unsigned int minorVersion,
-                                 const PlatformIdentifier platform,
-                                 const VersionCondition condition);
-
 /* This is used to dynamically load DLLs */
 HMODULE Curl_load_library(LPCTSTR filename);
 
diff --git a/lib/transfer.c b/lib/transfer.c
index 133a478..a07c7af 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -487,6 +487,12 @@ CURLcode Curl_readrewind(struct connectdata *conn)
 static int data_pending(const struct Curl_easy *data)
 {
   struct connectdata *conn = data->conn;
+
+#ifdef ENABLE_QUIC
+  if(conn->transport == TRNSPRT_QUIC)
+    return Curl_quic_data_pending(data);
+#endif
+
   /* in the case of libssh2, we can never be really sure that we have emptied
      its internal buffers so we MUST always try until we get EAGAIN back */
   return conn->handler->protocol&(CURLPROTO_SCP|CURLPROTO_SFTP) ||
@@ -500,8 +506,6 @@ static int data_pending(const struct Curl_easy *data)
        be called and we cannot signal the HTTP/2 stream has closed. As
        a workaround, we return nonzero here to call http2_recv. */
     ((conn->handler->protocol&PROTO_FAMILY_HTTP) && conn->httpversion >= 20);
-#elif defined(ENABLE_QUIC)
-    Curl_ssl_data_pending(conn, FIRSTSOCKET) || Curl_quic_data_pending(data);
 #else
     Curl_ssl_data_pending(conn, FIRSTSOCKET);
 #endif
@@ -1441,8 +1445,9 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
 
   if(!data->change.url && data->set.uh) {
     CURLUcode uc;
+    free(data->set.str[STRING_SET_URL]);
     uc = curl_url_get(data->set.uh,
-                        CURLUPART_URL, &data->set.str[STRING_SET_URL], 0);
+                      CURLUPART_URL, &data->set.str[STRING_SET_URL], 0);
     if(uc) {
       failf(data, "No URL set!");
       return CURLE_URL_MALFORMAT;
@@ -1799,12 +1804,14 @@ CURLcode Curl_retry_request(struct connectdata *conn,
   }
   if(retry) {
 #define CONN_MAX_RETRIES 5
-    if(conn->retrycount++ >= CONN_MAX_RETRIES) {
+    if(data->state.retrycount++ >= CONN_MAX_RETRIES) {
       failf(data, "Connection died, tried %d times before giving up",
             CONN_MAX_RETRIES);
+      data->state.retrycount = 0;
       return CURLE_SEND_ERROR;
     }
-    infof(conn->data, "Connection died, retrying a fresh connect\n");
+    infof(conn->data, "Connection died, retrying a fresh connect\
+(retry count: %d)\n", data->state.retrycount);
     *url = strdup(conn->data->change.url);
     if(!*url)
       return CURLE_OUT_OF_MEMORY;
diff --git a/lib/url.c b/lib/url.c
index a1a6b69..150667a 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -630,7 +630,7 @@ CURLcode Curl_open(struct Curl_easy **curl)
     Curl_initinfo(data);
 
     /* most recent connection is not yet defined */
-    data->state.lastconnect = NULL;
+    data->state.lastconnect_id = -1;
 
     data->progress.flags |= PGRS_HIDE;
     data->state.current_speed = -1; /* init to negative == impossible */
@@ -1836,11 +1836,12 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
   CURLU *uh;
   CURLUcode uc;
   char *hostname;
+  bool use_set_uh = (data->set.uh && !data->state.this_is_a_follow);
 
   up_free(data); /* cleanup previous leftovers first */
 
   /* parse the URL */
-  if(data->set.uh) {
+  if(use_set_uh) {
     uh = data->state.uh = curl_url_dup(data->set.uh);
   }
   else {
@@ -1863,7 +1864,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
     data->change.url_alloc = TRUE;
   }
 
-  if(!data->set.uh) {
+  if(!use_set_uh) {
     char *newurl;
     uc = curl_url_set(uh, CURLUPART_URL, data->change.url,
                     CURLU_GUESS_SCHEME |
@@ -3170,7 +3171,7 @@ static CURLcode resolve_server(struct Curl_easy *data,
   else {
     /* this is a fresh connect */
     int rc;
-    struct Curl_dns_entry *hostaddr;
+    struct Curl_dns_entry *hostaddr = NULL;
 
 #ifdef USE_UNIX_SOCKETS
     if(conn->unix_domain_socket) {
diff --git a/lib/urldata.h b/lib/urldata.h
index f80a02d..0ae9269 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -1090,7 +1090,6 @@ struct connectdata {
   struct http_connect_state *connect_state; /* for HTTP CONNECT */
   struct connectbundle *bundle; /* The bundle we are member of */
   int negnpn; /* APLN or NPN TLS negotiated protocol, CURL_HTTP_VERSION* */
-  int retrycount; /* number of retries on a new connection */
 #ifdef USE_UNIX_SOCKETS
   char *unix_domain_socket;
 #endif
@@ -1195,7 +1194,6 @@ typedef enum {
   HTTPREQ_POST_MIME, /* we make a difference internally */
   HTTPREQ_PUT,
   HTTPREQ_HEAD,
-  HTTPREQ_OPTIONS,
   HTTPREQ_LAST /* last in list */
 } Curl_HttpReq;
 
@@ -1297,10 +1295,12 @@ struct UrlState {
   /* Points to the connection cache */
   struct conncache *conn_cache;
 
+  int retrycount; /* number of retries on a new connection */
+
   /* buffers to store authentication data in, as parsed from input options */
   struct curltime keeps_speed; /* for the progress meter really */
 
-  struct connectdata *lastconnect; /* The last connection, NULL if undefined */
+  long lastconnect_id; /* The last connection, -1 if undefined */
   struct dynbuf headerb; /* buffer to store headers in */
 
   char *buffer; /* download buffer */
diff --git a/lib/vauth/ntlm.c b/lib/vauth/ntlm.c
index 3b46e1a..ecfeacb 100644
--- a/lib/vauth/ntlm.c
+++ b/lib/vauth/ntlm.c
@@ -191,6 +191,7 @@ static CURLcode ntlm_decode_type2_target(struct Curl_easy *data,
         return CURLE_BAD_CONTENT_ENCODING;
       }
 
+      free(ntlm->target_info); /* replace any previous data */
       ntlm->target_info = malloc(target_info_len);
       if(!ntlm->target_info)
         return CURLE_OUT_OF_MEMORY;
diff --git a/lib/version.c b/lib/version.c
index 14e5096..4f6dda2 100644
--- a/lib/version.c
+++ b/lib/version.c
@@ -66,6 +66,10 @@
 #include <brotli/decode.h>
 #endif
 
+#ifdef HAVE_ZSTD
+#include <zstd.h>
+#endif
+
 #ifdef HAVE_BROTLI
 static size_t brotli_version(char *buf, size_t bufsz)
 {
@@ -78,6 +82,20 @@ static size_t brotli_version(char *buf, size_t bufsz)
 }
 #endif
 
+#ifdef HAVE_ZSTD
+static size_t zstd_version(char *buf, size_t bufsz)
+{
+  unsigned long zstd_version = (unsigned long)ZSTD_versionNumber();
+  unsigned int major = (unsigned int)(zstd_version / (100 * 100));
+  unsigned int minor = (unsigned int)((zstd_version -
+                         (major * 100 * 100)) / 100);
+  unsigned int patch = (unsigned int)(zstd_version -
+                         (major * 100 * 100) - (minor * 100));
+
+  return msnprintf(buf, bufsz, "%u.%u.%u", major, minor, patch);
+}
+#endif
+
 /*
  * curl_version() returns a pointer to a static buffer.
  *
@@ -103,6 +121,9 @@ char *curl_version(void)
 #ifdef HAVE_BROTLI
   char br_version[40] = "brotli/";
 #endif
+#ifdef HAVE_ZSTD
+  char zst_version[40] = "zstd/";
+#endif
 #ifdef USE_ARES
   char cares_version[40];
 #endif
@@ -153,6 +174,10 @@ char *curl_version(void)
   brotli_version(&br_version[7], sizeof(br_version) - 7);
   src[i++] = br_version;
 #endif
+#ifdef HAVE_ZSTD
+  zstd_version(&zst_version[5], sizeof(zst_version) - 5);
+  src[i++] = zst_version;
+#endif
 #ifdef USE_ARES
   msnprintf(cares_version, sizeof(cares_version),
             "c-ares/%s", ares_version(NULL));
@@ -365,6 +390,9 @@ static curl_version_info_data version_info = {
     ( (SIZEOF_OFF_T > 4) || defined(USE_WIN32_LARGE_FILES) )
   | CURL_VERSION_LARGEFILE
 #endif
+#if defined(WIN32) && defined(UNICODE) && defined(_UNICODE)
+  | CURL_VERSION_UNICODE
+#endif
 #if defined(CURL_DOES_CONVERSIONS)
   | CURL_VERSION_CONV
 #endif
@@ -389,6 +417,9 @@ static curl_version_info_data version_info = {
 #if defined(HAVE_BROTLI)
   | CURL_VERSION_BROTLI
 #endif
+#if defined(HAVE_ZSTD)
+  | CURL_VERSION_ZSTD
+#endif
 #if defined(USE_ALTSVC)
   | CURL_VERSION_ALTSVC
 #endif
@@ -413,10 +444,12 @@ static curl_version_info_data version_info = {
   NULL,
 #endif
 #ifdef CURL_CA_PATH
-  CURL_CA_PATH  /* capath */
+  CURL_CA_PATH,  /* capath */
 #else
-  NULL
+  NULL,
 #endif
+  0,    /* zstd_ver_num */
+  NULL  /* zstd version */
 };
 
 curl_version_info_data *curl_version_info(CURLversion stamp)
@@ -434,6 +467,10 @@ curl_version_info_data *curl_version_info(CURLversion stamp)
 #ifdef HAVE_BROTLI
   static char brotli_buffer[80];
 #endif
+#ifdef HAVE_ZSTD
+  static char zstd_buffer[80];
+#endif
+
 
 #ifdef USE_SSL
   Curl_ssl_version(ssl_buffer, sizeof(ssl_buffer));
@@ -485,6 +522,12 @@ curl_version_info_data *curl_version_info(CURLversion stamp)
   version_info.brotli_version = brotli_buffer;
 #endif
 
+#ifdef HAVE_ZSTD
+  version_info.zstd_ver_num = (unsigned int)ZSTD_versionNumber();
+  zstd_version(zstd_buffer, sizeof(zstd_buffer));
+  version_info.zstd_version = zstd_buffer;
+#endif
+
 #ifdef USE_NGHTTP2
   {
     nghttp2_info *h2 = nghttp2_version(0);
diff --git a/lib/version_win32.c b/lib/version_win32.c
new file mode 100644
index 0000000..6561d36
--- /dev/null
+++ b/lib/version_win32.c
@@ -0,0 +1,226 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2016 - 2020, Steve Holme, <steve_holme@hotmail.com>.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(WIN32)
+
+#include <curl/curl.h>
+#include "version_win32.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+/*
+ * curlx_verify_windows_version()
+ *
+ * This is used to verify if we are running on a specific windows version.
+ *
+ * Parameters:
+ *
+ * majorVersion [in] - The major version number.
+ * minorVersion [in] - The minor version number.
+ * platform     [in] - The optional platform identifier.
+ * condition    [in] - The test condition used to specifier whether we are
+ *                     checking a version less then, equal to or greater than
+ *                     what is specified in the major and minor version
+ *                     numbers.
+ *
+ * Returns TRUE if matched; otherwise FALSE.
+ */
+bool curlx_verify_windows_version(const unsigned int majorVersion,
+                                  const unsigned int minorVersion,
+                                  const PlatformIdentifier platform,
+                                  const VersionCondition condition)
+{
+  bool matched = FALSE;
+
+#if defined(CURL_WINDOWS_APP)
+  /* We have no way to determine the Windows version from Windows apps,
+     so let's assume we're running on the target Windows version. */
+  const WORD fullVersion = MAKEWORD(minorVersion, majorVersion);
+  const WORD targetVersion = (WORD)_WIN32_WINNT;
+
+  switch(condition) {
+  case VERSION_LESS_THAN:
+    matched = targetVersion < fullVersion;
+    break;
+
+  case VERSION_LESS_THAN_EQUAL:
+    matched = targetVersion <= fullVersion;
+    break;
+
+  case VERSION_EQUAL:
+    matched = targetVersion == fullVersion;
+    break;
+
+  case VERSION_GREATER_THAN_EQUAL:
+    matched = targetVersion >= fullVersion;
+    break;
+
+  case VERSION_GREATER_THAN:
+    matched = targetVersion > fullVersion;
+    break;
+  }
+
+  if(matched && (platform == PLATFORM_WINDOWS)) {
+    /* we're always running on PLATFORM_WINNT */
+    matched = FALSE;
+  }
+#elif !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \
+    (_WIN32_WINNT < _WIN32_WINNT_WIN2K)
+  OSVERSIONINFO osver;
+
+  memset(&osver, 0, sizeof(osver));
+  osver.dwOSVersionInfoSize = sizeof(osver);
+
+  /* Find out Windows version */
+  if(GetVersionEx(&osver)) {
+    /* Verify the Operating System version number */
+    switch(condition) {
+    case VERSION_LESS_THAN:
+      if(osver.dwMajorVersion < majorVersion ||
+        (osver.dwMajorVersion == majorVersion &&
+         osver.dwMinorVersion < minorVersion))
+        matched = TRUE;
+      break;
+
+    case VERSION_LESS_THAN_EQUAL:
+      if(osver.dwMajorVersion < majorVersion ||
+        (osver.dwMajorVersion == majorVersion &&
+         osver.dwMinorVersion <= minorVersion))
+        matched = TRUE;
+      break;
+
+    case VERSION_EQUAL:
+      if(osver.dwMajorVersion == majorVersion &&
+         osver.dwMinorVersion == minorVersion)
+        matched = TRUE;
+      break;
+
+    case VERSION_GREATER_THAN_EQUAL:
+      if(osver.dwMajorVersion > majorVersion ||
+        (osver.dwMajorVersion == majorVersion &&
+         osver.dwMinorVersion >= minorVersion))
+        matched = TRUE;
+      break;
+
+    case VERSION_GREATER_THAN:
+      if(osver.dwMajorVersion > majorVersion ||
+        (osver.dwMajorVersion == majorVersion &&
+         osver.dwMinorVersion > minorVersion))
+        matched = TRUE;
+      break;
+    }
+
+    /* Verify the platform identifier (if necessary) */
+    if(matched) {
+      switch(platform) {
+      case PLATFORM_WINDOWS:
+        if(osver.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS)
+          matched = FALSE;
+        break;
+
+      case PLATFORM_WINNT:
+        if(osver.dwPlatformId != VER_PLATFORM_WIN32_NT)
+          matched = FALSE;
+
+      default: /* like platform == PLATFORM_DONT_CARE */
+        break;
+      }
+    }
+  }
+#else
+  ULONGLONG cm = 0;
+  OSVERSIONINFOEX osver;
+  BYTE majorCondition;
+  BYTE minorCondition;
+  BYTE spMajorCondition;
+  BYTE spMinorCondition;
+
+  switch(condition) {
+  case VERSION_LESS_THAN:
+    majorCondition = VER_LESS;
+    minorCondition = VER_LESS;
+    spMajorCondition = VER_LESS_EQUAL;
+    spMinorCondition = VER_LESS_EQUAL;
+    break;
+
+  case VERSION_LESS_THAN_EQUAL:
+    majorCondition = VER_LESS_EQUAL;
+    minorCondition = VER_LESS_EQUAL;
+    spMajorCondition = VER_LESS_EQUAL;
+    spMinorCondition = VER_LESS_EQUAL;
+    break;
+
+  case VERSION_EQUAL:
+    majorCondition = VER_EQUAL;
+    minorCondition = VER_EQUAL;
+    spMajorCondition = VER_GREATER_EQUAL;
+    spMinorCondition = VER_GREATER_EQUAL;
+    break;
+
+  case VERSION_GREATER_THAN_EQUAL:
+    majorCondition = VER_GREATER_EQUAL;
+    minorCondition = VER_GREATER_EQUAL;
+    spMajorCondition = VER_GREATER_EQUAL;
+    spMinorCondition = VER_GREATER_EQUAL;
+    break;
+
+  case VERSION_GREATER_THAN:
+    majorCondition = VER_GREATER;
+    minorCondition = VER_GREATER;
+    spMajorCondition = VER_GREATER_EQUAL;
+    spMinorCondition = VER_GREATER_EQUAL;
+    break;
+
+  default:
+    return FALSE;
+  }
+
+  memset(&osver, 0, sizeof(osver));
+  osver.dwOSVersionInfoSize = sizeof(osver);
+  osver.dwMajorVersion = majorVersion;
+  osver.dwMinorVersion = minorVersion;
+  if(platform == PLATFORM_WINDOWS)
+    osver.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS;
+  else if(platform == PLATFORM_WINNT)
+    osver.dwPlatformId = VER_PLATFORM_WIN32_NT;
+
+  cm = VerSetConditionMask(cm, VER_MAJORVERSION, majorCondition);
+  cm = VerSetConditionMask(cm, VER_MINORVERSION, minorCondition);
+  cm = VerSetConditionMask(cm, VER_SERVICEPACKMAJOR, spMajorCondition);
+  cm = VerSetConditionMask(cm, VER_SERVICEPACKMINOR, spMinorCondition);
+  if(platform != PLATFORM_DONT_CARE)
+    cm = VerSetConditionMask(cm, VER_PLATFORMID, VER_EQUAL);
+
+  if(VerifyVersionInfo(&osver, (VER_MAJORVERSION | VER_MINORVERSION |
+                                VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR),
+                       cm))
+    matched = TRUE;
+#endif
+
+  return matched;
+}
+
+#endif /* WIN32 */
diff --git a/lib/version_win32.h b/lib/version_win32.h
new file mode 100644
index 0000000..94cc626
--- /dev/null
+++ b/lib/version_win32.h
@@ -0,0 +1,53 @@
+#ifndef HEADER_CURL_VERSION_WIN32_H
+#define HEADER_CURL_VERSION_WIN32_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2016 - 2020, Steve Holme, <steve_holme@hotmail.com>.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(WIN32)
+
+/* Version condition */
+typedef enum {
+  VERSION_LESS_THAN,
+  VERSION_LESS_THAN_EQUAL,
+  VERSION_EQUAL,
+  VERSION_GREATER_THAN_EQUAL,
+  VERSION_GREATER_THAN
+} VersionCondition;
+
+/* Platform identifier */
+typedef enum {
+  PLATFORM_DONT_CARE,
+  PLATFORM_WINDOWS,
+  PLATFORM_WINNT
+} PlatformIdentifier;
+
+/* This is used to verify if we are running on a specific windows version */
+bool curlx_verify_windows_version(const unsigned int majorVersion,
+                                  const unsigned int minorVersion,
+                                  const PlatformIdentifier platform,
+                                  const VersionCondition condition);
+
+#endif /* WIN32 */
+
+#endif /* HEADER_CURL_VERSION_WIN32_H */
diff --git a/lib/vquic/ngtcp2.c b/lib/vquic/ngtcp2.c
index d29cb37..20ee08d 100644
--- a/lib/vquic/ngtcp2.c
+++ b/lib/vquic/ngtcp2.c
@@ -150,9 +150,11 @@ quic_from_gtls_level(gnutls_record_encryption_level_t gtls_level)
 }
 #endif
 
-static void qlog_callback(void *user_data, const void *data, size_t datalen)
+static void qlog_callback(void *user_data, uint32_t flags,
+                          const void *data, size_t datalen)
 {
   struct quicsocket *qs = (struct quicsocket *)user_data;
+  (void)flags;
   if(qs->qlogfd != -1) {
     ssize_t rc = write(qs->qlogfd, data, datalen);
     if(rc == -1) {
@@ -826,9 +828,8 @@ CURLcode Curl_quic_connect(struct connectdata *conn,
   if(rv == -1)
     return CURLE_QUIC_CONNECT_ERROR;
 
-  ngtcp2_addr_init(&path.local, (uint8_t *)&qs->local_addr, qs->local_addrlen,
-                   NULL);
-  ngtcp2_addr_init(&path.remote, (uint8_t*)addr, addrlen, NULL);
+  ngtcp2_addr_init(&path.local, &qs->local_addr, qs->local_addrlen, NULL);
+  ngtcp2_addr_init(&path.remote, addr, addrlen, NULL);
 
 #ifdef NGTCP2_PROTO_VER
 #define QUICVER NGTCP2_PROTO_VER
@@ -1744,10 +1745,10 @@ static CURLcode ng_process_ingress(struct connectdata *conn, int sockfd,
       return CURLE_RECV_ERROR;
     }
 
-    ngtcp2_addr_init(&path.local, (uint8_t *)&qs->local_addr,
+    ngtcp2_addr_init(&path.local, &qs->local_addr,
                      qs->local_addrlen, NULL);
-    ngtcp2_addr_init(&path.remote, (uint8_t *)&remote_addr, remote_addrlen,
-                     NULL);
+    ngtcp2_addr_init(&path.remote, (struct sockaddr *)&remote_addr,
+                     remote_addrlen, NULL);
 
     rv = ngtcp2_conn_read_pkt(qs->qconn, &path, buf, recvd, ts);
     if(rv != 0) {
@@ -1778,7 +1779,7 @@ static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd,
   nghttp3_vec vec[16];
   ssize_t ndatalen;
 
-  switch(qs->local_addr.ss_family) {
+  switch(qs->local_addr.sa_family) {
   case AF_INET:
     pktlen = NGTCP2_MAX_PKTLEN_IPV4;
     break;
@@ -1834,7 +1835,7 @@ static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd,
             }
             continue;
           }
-          else if(outlen == NGTCP2_ERR_WRITE_STREAM_MORE) {
+          else if(outlen == NGTCP2_ERR_WRITE_MORE) {
             assert(ndatalen > 0);
             rv = nghttp3_conn_add_write_offset(qs->h3conn, stream_id,
                                                ndatalen);
diff --git a/lib/vquic/ngtcp2.h b/lib/vquic/ngtcp2.h
index e2f8b56..afdd01b 100644
--- a/lib/vquic/ngtcp2.h
+++ b/lib/vquic/ngtcp2.h
@@ -58,7 +58,7 @@ struct quicsocket {
   struct quic_handshake crypto_data[3];
   /* the last TLS alert description generated by the local endpoint */
   uint8_t tls_alert;
-  struct sockaddr_storage local_addr;
+  struct sockaddr local_addr;
   socklen_t local_addrlen;
 
   nghttp3_conn *h3conn;
diff --git a/lib/vquic/quiche.c b/lib/vquic/quiche.c
index be6f15c..fd9cb8b 100644
--- a/lib/vquic/quiche.c
+++ b/lib/vquic/quiche.c
@@ -95,8 +95,14 @@ static CURLcode qs_disconnect(struct quicsocket *qs)
     quiche_h3_config_free(qs->h3config);
   if(qs->h3c)
     quiche_h3_conn_free(qs->h3c);
-  quiche_config_free(qs->cfg);
-  quiche_conn_free(qs->conn);
+  if(qs->cfg) {
+    quiche_config_free(qs->cfg);
+    qs->cfg = NULL;
+  }
+  if(qs->conn) {
+    quiche_conn_free(qs->conn);
+    qs->conn = NULL;
+  }
   return CURLE_OK;
 }
 
diff --git a/lib/vssh/libssh2.c b/lib/vssh/libssh2.c
index 555afc9..4f56bb4 100644
--- a/lib/vssh/libssh2.c
+++ b/lib/vssh/libssh2.c
@@ -1256,7 +1256,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
           result = CURLE_SSH;
         sshc->actualcode = result;
         DEBUGF(infof(data, "error = %d makes libcurl = %d\n",
-                     ssherr, (int)result));
+                     sftperr, (int)result));
         state(conn, SSH_STOP);
         break;
       }
diff --git a/lib/vtls/bearssl.c b/lib/vtls/bearssl.c
index 628e16a..44e7406 100644
--- a/lib/vtls/bearssl.c
+++ b/lib/vtls/bearssl.c
@@ -300,8 +300,12 @@ static CURLcode bearssl_connect_step1(struct connectdata *conn, int sockindex)
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   struct ssl_backend_data *backend = connssl->backend;
   const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
+#ifndef CURL_DISABLE_PROXY
   const char *hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
     conn->host.name;
+#else
+  const char *hostname = conn->host.name;
+#endif
   const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
   const bool verifyhost = SSL_CONN_CONFIG(verifyhost);
   CURLcode ret;
@@ -386,8 +390,11 @@ static CURLcode bearssl_connect_step1(struct connectdata *conn, int sockindex)
      */
 
 #ifdef USE_NGHTTP2
-    if(data->set.httpversion >= CURL_HTTP_VERSION_2 &&
-       (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) {
+    if(data->set.httpversion >= CURL_HTTP_VERSION_2
+#ifndef CURL_DISABLE_PROXY
+      && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)
+#endif
+      ) {
       backend->protocols[cur++] = NGHTTP2_PROTO_VERSION_ID;
       infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
     }
diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c
index 9b4c365..16b0bd6 100644
--- a/lib/vtls/gtls.c
+++ b/lib/vtls/gtls.c
@@ -399,10 +399,15 @@ gtls_connect_step1(struct connectdata *conn,
 #endif
   const char *prioritylist;
   const char *err = NULL;
+#ifndef CURL_DISABLE_PROXY
   const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
     conn->host.name;
   long * const certverifyresult = SSL_IS_PROXY() ?
     &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
+#else
+  const char * const hostname = conn->host.name;
+  long * const certverifyresult = &data->set.ssl.certverifyresult;
+#endif
 
   if(connssl->state == ssl_connection_complete)
     /* to make us tolerant against being called more than once for the
@@ -620,8 +625,11 @@ gtls_connect_step1(struct connectdata *conn,
     gnutls_datum_t protocols[2];
 
 #ifdef USE_NGHTTP2
-    if(data->set.httpversion >= CURL_HTTP_VERSION_2 &&
-       (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) {
+    if(data->set.httpversion >= CURL_HTTP_VERSION_2
+#ifndef CURL_DISABLE_PROXY
+       && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)
+#endif
+       ) {
       protocols[cur].data = (unsigned char *)NGHTTP2_PROTO_VERSION_ID;
       protocols[cur].size = NGHTTP2_PROTO_VERSION_ID_LEN;
       cur++;
@@ -694,12 +702,15 @@ gtls_connect_step1(struct connectdata *conn,
     }
   }
 
+#ifndef CURL_DISABLE_PROXY
   if(conn->proxy_ssl[sockindex].use) {
     transport_ptr = conn->proxy_ssl[sockindex].backend->session;
     gnutls_transport_push = Curl_gtls_push_ssl;
     gnutls_transport_pull = Curl_gtls_pull_ssl;
   }
-  else {
+  else
+#endif
+  {
     /* file descriptor for the socket */
     transport_ptr = &conn->sock[sockindex];
     gnutls_transport_push = Curl_gtls_push;
@@ -828,10 +839,15 @@ gtls_connect_step3(struct connectdata *conn,
   unsigned int bits;
   gnutls_protocol_t version = gnutls_protocol_get_version(session);
 #endif
+#ifndef CURL_DISABLE_PROXY
   const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
     conn->host.name;
   long * const certverifyresult = SSL_IS_PROXY() ?
     &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
+#else
+  const char * const hostname = conn->host.name;
+  long * const certverifyresult = &data->set.ssl.certverifyresult;
+#endif
 
   /* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */
   ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session),
@@ -1112,8 +1128,12 @@ gtls_connect_step3(struct connectdata *conn,
   }
 #endif
   if(!rc) {
+#ifndef CURL_DISABLE_PROXY
     const char * const dispname = SSL_IS_PROXY() ?
       conn->http_proxy.host.dispname : conn->host.dispname;
+#else
+    const char * const dispname = conn->host.dispname;
+#endif
 
     if(SSL_CONN_CONFIG(verifyhost)) {
       failf(data, "SSL: certificate subject name (%s) does not match "
@@ -1216,20 +1236,23 @@ gtls_connect_step3(struct connectdata *conn,
 
 
   rc = gnutls_x509_crt_get_dn2(x509_cert, &certfields);
-  if(rc != 0)
-    return CURLE_OUT_OF_MEMORY;
-  infof(data, "\t subject: %s\n", certfields.data);
+  if(rc)
+    infof(data, "Failed to get certificate name\n");
+  else {
+    infof(data, "\t subject: %s\n", certfields.data);
 
-  certclock = gnutls_x509_crt_get_activation_time(x509_cert);
-  showtime(data, "start date", certclock);
+    certclock = gnutls_x509_crt_get_activation_time(x509_cert);
+    showtime(data, "start date", certclock);
 
-  certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
-  showtime(data, "expire date", certclock);
+    certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
+    showtime(data, "expire date", certclock);
+  }
 
   rc = gnutls_x509_crt_get_issuer_dn2(x509_cert, &certfields);
-  if(rc != 0)
-    return CURLE_OUT_OF_MEMORY;
-  infof(data, "\t issuer: %s\n", certfields.data);
+  if(rc)
+    infof(data, "Failed to get certificate issuer\n");
+  else
+    infof(data, "\t issuer: %s\n", certfields.data);
 #endif
 
   gnutls_x509_crt_deinit(x509_cert);
@@ -1381,10 +1404,13 @@ static bool Curl_gtls_data_pending(const struct connectdata *conn,
      0 != gnutls_record_check_pending(backend->session))
     res = TRUE;
 
+#ifndef CURL_DISABLE_PROXY
   connssl = &conn->proxy_ssl[connindex];
+  backend = connssl->backend;
   if(backend->session &&
      0 != gnutls_record_check_pending(backend->session))
     res = TRUE;
+#endif
 
   return res;
 }
@@ -1433,7 +1459,9 @@ static void close_one(struct ssl_connect_data *connssl)
 static void Curl_gtls_close(struct connectdata *conn, int sockindex)
 {
   close_one(&conn->ssl[sockindex]);
+#ifndef CURL_DISABLE_PROXY
   close_one(&conn->proxy_ssl[sockindex]);
+#endif
 }
 
 /*
diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c
index fca2926..0f0d1ee 100644
--- a/lib/vtls/nss.c
+++ b/lib/vtls/nss.c
@@ -1027,9 +1027,11 @@ static SECStatus BadCertHandler(void *arg, PRFileDesc *sock)
   CERTCertificate *cert;
 
   /* remember the cert verification result */
+#ifndef CURL_DISABLE_PROXY
   if(SSL_IS_PROXY())
     data->set.proxy_ssl.certverifyresult = err;
   else
+#endif
     data->set.ssl.certverifyresult = err;
 
   if(err == SSL_ERROR_BAD_CERT_DOMAIN && !SSL_CONN_CONFIG(verifyhost))
@@ -1553,24 +1555,32 @@ static void nss_close(struct ssl_connect_data *connssl)
 static void Curl_nss_close(struct connectdata *conn, int sockindex)
 {
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+#ifndef CURL_DISABLE_PROXY
   struct ssl_connect_data *connssl_proxy = &conn->proxy_ssl[sockindex];
+#endif
   struct ssl_backend_data *backend = connssl->backend;
 
-  if(backend->handle || connssl_proxy->backend->handle) {
+  if(backend->handle
+#ifndef CURL_DISABLE_PROXY
+    || connssl_proxy->backend->handle
+#endif
+    ) {
     /* NSS closes the socket we previously handed to it, so we must mark it
        as closed to avoid double close */
     fake_sclose(conn->sock[sockindex]);
     conn->sock[sockindex] = CURL_SOCKET_BAD;
   }
 
+#ifndef CURL_DISABLE_PROXY
   if(backend->handle)
     /* nss_close(connssl) will transitively close also
        connssl_proxy->backend->handle if both are used. Clear it to avoid
        a double close leading to crash. */
     connssl_proxy->backend->handle = NULL;
 
-  nss_close(connssl);
   nss_close(connssl_proxy);
+#endif
+  nss_close(connssl);
 }
 
 /* return true if NSS can provide error code (and possibly msg) for the
@@ -1828,6 +1838,12 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
   CURLcode result;
   bool second_layer = FALSE;
   SSLVersionRange sslver_supported;
+#ifndef CURL_DISABLE_PROXY
+  const char *hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+    conn->host.name;
+#else
+  const char *hostname = conn->host.name;
+#endif
 
   SSLVersionRange sslver = {
     SSL_LIBRARY_VERSION_TLS_1_0,  /* min */
@@ -1932,9 +1948,11 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
     goto error;
 
   /* not checked yet */
+#ifndef CURL_DISABLE_PROXY
   if(SSL_IS_PROXY())
     data->set.proxy_ssl.certverifyresult = 0;
   else
+#endif
     data->set.ssl.certverifyresult = 0;
 
   if(SSL_BadCertHook(model, BadCertHandler, conn) != SECSuccess)
@@ -1991,12 +2009,14 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
     goto error;
   }
 
+#ifndef CURL_DISABLE_PROXY
   if(conn->proxy_ssl[sockindex].use) {
     DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state);
     DEBUGASSERT(conn->proxy_ssl[sockindex].backend->handle != NULL);
     nspr_io = conn->proxy_ssl[sockindex].backend->handle;
     second_layer = TRUE;
   }
+#endif
   else {
     /* wrap OS file descriptor by NSPR's file descriptor abstraction */
     nspr_io = PR_ImportTCPSocket(sockfd);
@@ -2077,8 +2097,11 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
     unsigned char protocols[128];
 
 #ifdef USE_NGHTTP2
-    if(data->set.httpversion >= CURL_HTTP_VERSION_2 &&
-       (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) {
+    if(data->set.httpversion >= CURL_HTTP_VERSION_2
+#ifndef CURL_DISABLE_PROXY
+      && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)
+#endif
+      ) {
       protocols[cur++] = NGHTTP2_PROTO_VERSION_ID_LEN;
       memcpy(&protocols[cur], NGHTTP2_PROTO_VERSION_ID,
           NGHTTP2_PROTO_VERSION_ID_LEN);
@@ -2101,14 +2124,11 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
     goto error;
 
   /* propagate hostname to the TLS layer */
-  if(SSL_SetURL(backend->handle, SSL_IS_PROXY() ? conn->http_proxy.host.name :
-                conn->host.name) != SECSuccess)
+  if(SSL_SetURL(backend->handle, hostname) != SECSuccess)
     goto error;
 
   /* prevent NSS from re-using the session for a different hostname */
-  if(SSL_SetSockPeerID(backend->handle, SSL_IS_PROXY() ?
-                       conn->http_proxy.host.name : conn->host.name)
-     != SECSuccess)
+  if(SSL_SetSockPeerID(backend->handle, hostname) != SECSuccess)
     goto error;
 
   return CURLE_OK;
@@ -2127,11 +2147,17 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
   struct Curl_easy *data = conn->data;
   CURLcode result = CURLE_SSL_CONNECT_ERROR;
   PRUint32 timeout;
+#ifndef CURL_DISABLE_PROXY
   long * const certverifyresult = SSL_IS_PROXY() ?
     &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
   const char * const pinnedpubkey = SSL_IS_PROXY() ?
               data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
               data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+#else
+  long * const certverifyresult = &data->set.ssl.certverifyresult;
+  const char * const pinnedpubkey =
+              data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+#endif
 
 
   /* check timeout situation */
diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
index 2e9f900..1685a4a 100644
--- a/lib/vtls/openssl.c
+++ b/lib/vtls/openssl.c
@@ -619,7 +619,9 @@ SSL_CTX_use_certificate_chain_bio(SSL_CTX *ctx, BIO* in,
                                   const char *key_passwd)
 {
 /* SSL_CTX_add1_chain_cert introduced in OpenSSL 1.0.2 */
-#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) /* 1.0.2 or later */
+#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && /* OpenSSL 1.0.2 or later */ \
+    !(defined(LIBRESSL_VERSION_NUMBER) && \
+      (LIBRESSL_VERSION_NUMBER < 0x2090100fL)) /* LibreSSL 2.9.1 or later */
   int ret = 0;
   X509 *x = NULL;
   void *passwd_callback_userdata = (void *)key_passwd;
@@ -2825,7 +2827,8 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
   if((SSL_CONN_CONFIG(verifypeer) || SSL_CONN_CONFIG(verifyhost)) &&
      (SSL_SET_OPTION(native_ca_store))) {
     X509_STORE *store = SSL_CTX_get_cert_store(backend->ctx);
-    HCERTSTORE hStore = CertOpenSystemStoreA((HCRYPTPROV_LEGACY)NULL, "ROOT");
+    HCERTSTORE hStore = CertOpenSystemStore((HCRYPTPROV_LEGACY)NULL,
+                                            TEXT("ROOT"));
 
     if(hStore) {
       PCCERT_CONTEXT pContext = NULL;
diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c
index 1996526..1c1432d 100644
--- a/lib/vtls/schannel.c
+++ b/lib/vtls/schannel.c
@@ -50,7 +50,7 @@
 #include "x509asn1.h"
 #include "curl_printf.h"
 #include "multiif.h"
-#include "system_win32.h"
+#include "version_win32.h"
 
 /* The last #include file should be: */
 #include "curl_memory.h"
@@ -436,8 +436,8 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
                "schannel: SSL/TLS connection with %s port %hu (step 1/3)\n",
                hostname, conn->remote_port));
 
-  if(Curl_verify_windows_version(5, 1, PLATFORM_WINNT,
-                                 VERSION_LESS_THAN_EQUAL)) {
+  if(curlx_verify_windows_version(5, 1, PLATFORM_WINNT,
+                                  VERSION_LESS_THAN_EQUAL)) {
     /* Schannel in Windows XP (OS version 5.1) uses legacy handshakes and
        algorithms that may not be supported by all servers. */
     infof(data, "schannel: Windows version is old and may not be able to "
@@ -448,10 +448,10 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
   /* ALPN is only supported on Windows 8.1 / Server 2012 R2 and above.
      Also it doesn't seem to be supported for Wine, see curl bug #983. */
   BACKEND->use_alpn = conn->bits.tls_enable_alpn &&
-    !GetProcAddress(GetModuleHandleA("ntdll"),
+    !GetProcAddress(GetModuleHandle(TEXT("ntdll")),
                     "wine_get_version") &&
-    Curl_verify_windows_version(6, 3, PLATFORM_WINNT,
-                                VERSION_GREATER_THAN_EQUAL);
+    curlx_verify_windows_version(6, 3, PLATFORM_WINNT,
+                                 VERSION_GREATER_THAN_EQUAL);
 #else
   BACKEND->use_alpn = false;
 #endif
@@ -467,8 +467,8 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
 #else
 #ifdef HAS_MANUAL_VERIFY_API
   if(SSL_CONN_CONFIG(CAfile)) {
-    if(Curl_verify_windows_version(6, 1, PLATFORM_WINNT,
-                                   VERSION_GREATER_THAN_EQUAL)) {
+    if(curlx_verify_windows_version(6, 1, PLATFORM_WINNT,
+                                    VERSION_GREATER_THAN_EQUAL)) {
       BACKEND->use_manual_cred_validation = true;
     }
     else {
@@ -2015,8 +2015,8 @@ schannel_recv(struct connectdata *conn, int sockindex,
   */
   if(len && !BACKEND->decdata_offset && BACKEND->recv_connection_closed &&
      !BACKEND->recv_sspi_close_notify) {
-    bool isWin2k = Curl_verify_windows_version(5, 0, PLATFORM_WINNT,
-                                               VERSION_EQUAL);
+    bool isWin2k = curlx_verify_windows_version(5, 0, PLATFORM_WINNT,
+                                                VERSION_EQUAL);
 
     if(isWin2k && sspi_status == SEC_E_OK)
       BACKEND->recv_sspi_close_notify = true;
diff --git a/lib/vtls/schannel_verify.c b/lib/vtls/schannel_verify.c
index bdd7199..ab7be39 100644
--- a/lib/vtls/schannel_verify.c
+++ b/lib/vtls/schannel_verify.c
@@ -45,7 +45,7 @@
 #include "curl_multibyte.h"
 #include "curl_printf.h"
 #include "hostcheck.h"
-#include "system_win32.h"
+#include "version_win32.h"
 
 /* The last #include file should be: */
 #include "curl_memory.h"
@@ -317,8 +317,8 @@ static DWORD cert_get_name_string(struct Curl_easy *data,
   DWORD i;
 
   /* CERT_NAME_SEARCH_ALL_NAMES_FLAG is available from Windows 8 onwards. */
-  if(Curl_verify_windows_version(6, 2, PLATFORM_WINNT,
-                                 VERSION_GREATER_THAN_EQUAL)) {
+  if(curlx_verify_windows_version(6, 2, PLATFORM_WINNT,
+                                  VERSION_GREATER_THAN_EQUAL)) {
 #ifdef CERT_NAME_SEARCH_ALL_NAMES_FLAG
     /* CertGetNameString will provide the 8-bit character string without
      * any decoding */
@@ -564,7 +564,7 @@ CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex)
      * trusted certificates. This is only supported on Windows 7+.
      */
 
-    if(Curl_verify_windows_version(6, 1, PLATFORM_WINNT, VERSION_LESS_THAN)) {
+    if(curlx_verify_windows_version(6, 1, PLATFORM_WINNT, VERSION_LESS_THAN)) {
       failf(data, "schannel: this version of Windows is too old to support "
             "certificate verification via CA bundle file.");
       result = CURLE_SSL_CACERT_BADFILE;
diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c
index c3a55fb..281043a 100644
--- a/lib/vtls/vtls.c
+++ b/lib/vtls/vtls.c
@@ -621,6 +621,7 @@ void Curl_ssl_close(struct connectdata *conn, int sockindex)
 {
   DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
   Curl_ssl->close_one(conn, sockindex);
+  conn->ssl[sockindex].state = ssl_connection_none;
 }
 
 CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex)
-- 
cgit v0.12