summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2023-08-01 17:58:24 (GMT)
committerBrad King <brad.king@kitware.com>2023-08-01 17:58:24 (GMT)
commit188c065e5a447e4c659426e0c27051928c8adb6e (patch)
tree91af173dfc4e42b50510e998778aa4886d68faeb
parent1345c21275574dd66f7adadc9123682488856ba1 (diff)
parente2ab2da70a2b390eb9067d45dfa47023b00c5cd7 (diff)
downloadCMake-188c065e5a447e4c659426e0c27051928c8adb6e.zip
CMake-188c065e5a447e4c659426e0c27051928c8adb6e.tar.gz
CMake-188c065e5a447e4c659426e0c27051928c8adb6e.tar.bz2
Merge branch 'upstream-curl' into update-curl
* upstream-curl: curl 2023-07-26 (50490c06)
-rw-r--r--Utilities/cmcurl/CMake/FindNGTCP2.cmake4
-rw-r--r--Utilities/cmcurl/CMakeLists.txt10
-rw-r--r--Utilities/cmcurl/include/curl/curl.h16
-rw-r--r--Utilities/cmcurl/include/curl/curlver.h8
-rw-r--r--Utilities/cmcurl/include/curl/system.h47
-rw-r--r--Utilities/cmcurl/include/curl/typecheck-gcc.h1
-rw-r--r--Utilities/cmcurl/include/curl/websockets.h12
-rw-r--r--Utilities/cmcurl/lib/CMakeLists.txt15
-rw-r--r--Utilities/cmcurl/lib/Makefile.inc3
-rw-r--r--Utilities/cmcurl/lib/altsvc.c5
-rw-r--r--Utilities/cmcurl/lib/amigaos.c1
-rw-r--r--Utilities/cmcurl/lib/base64.c6
-rw-r--r--Utilities/cmcurl/lib/bufq.c29
-rw-r--r--Utilities/cmcurl/lib/c-hyper.c11
-rw-r--r--Utilities/cmcurl/lib/cf-h1-proxy.c124
-rw-r--r--Utilities/cmcurl/lib/cf-h2-proxy.c531
-rw-r--r--Utilities/cmcurl/lib/cf-haproxy.c11
-rw-r--r--Utilities/cmcurl/lib/cf-https-connect.c12
-rw-r--r--Utilities/cmcurl/lib/cf-socket.c77
-rw-r--r--Utilities/cmcurl/lib/cfilters.c14
-rw-r--r--Utilities/cmcurl/lib/cfilters.h4
-rw-r--r--Utilities/cmcurl/lib/conncache.h3
-rw-r--r--Utilities/cmcurl/lib/connect.c6
-rw-r--r--Utilities/cmcurl/lib/cookie.c9
-rw-r--r--Utilities/cmcurl/lib/curl_config.h.cmake6
-rw-r--r--Utilities/cmcurl/lib/curl_log.c6
-rw-r--r--Utilities/cmcurl/lib/curl_log.h31
-rw-r--r--Utilities/cmcurl/lib/curl_memory.h58
-rw-r--r--Utilities/cmcurl/lib/curl_printf.h1
-rw-r--r--Utilities/cmcurl/lib/curl_sasl.c18
-rw-r--r--Utilities/cmcurl/lib/curl_setup.h3
-rw-r--r--Utilities/cmcurl/lib/curl_setup_once.h6
-rw-r--r--Utilities/cmcurl/lib/dynbuf.h2
-rw-r--r--Utilities/cmcurl/lib/easy.c18
-rw-r--r--Utilities/cmcurl/lib/easy_lock.h4
-rw-r--r--Utilities/cmcurl/lib/easyoptions.c7
-rw-r--r--Utilities/cmcurl/lib/fopen.c14
-rw-r--r--Utilities/cmcurl/lib/ftp.c130
-rw-r--r--Utilities/cmcurl/lib/getinfo.c7
-rw-r--r--Utilities/cmcurl/lib/hostip.c30
-rw-r--r--Utilities/cmcurl/lib/hsts.c5
-rw-r--r--Utilities/cmcurl/lib/http.c32
-rw-r--r--Utilities/cmcurl/lib/http1.c129
-rw-r--r--Utilities/cmcurl/lib/http1.h4
-rw-r--r--Utilities/cmcurl/lib/http2.c332
-rw-r--r--Utilities/cmcurl/lib/http_proxy.c4
-rw-r--r--Utilities/cmcurl/lib/imap.c96
-rw-r--r--Utilities/cmcurl/lib/krb5.c2
-rw-r--r--Utilities/cmcurl/lib/ldap.c8
-rw-r--r--Utilities/cmcurl/lib/macos.c62
-rw-r--r--Utilities/cmcurl/lib/macos.h38
-rw-r--r--Utilities/cmcurl/lib/mime.c16
-rw-r--r--Utilities/cmcurl/lib/mqtt.c2
-rw-r--r--Utilities/cmcurl/lib/multi.c57
-rw-r--r--Utilities/cmcurl/lib/pop3.c44
-rw-r--r--Utilities/cmcurl/lib/sendf.c2
-rw-r--r--Utilities/cmcurl/lib/setopt.c11
-rw-r--r--Utilities/cmcurl/lib/smb.c195
-rw-r--r--Utilities/cmcurl/lib/smb.h197
-rw-r--r--Utilities/cmcurl/lib/smtp.c44
-rw-r--r--Utilities/cmcurl/lib/socks.c19
-rw-r--r--Utilities/cmcurl/lib/telnet.c5
-rw-r--r--Utilities/cmcurl/lib/timeval.c16
-rw-r--r--Utilities/cmcurl/lib/transfer.c16
-rw-r--r--Utilities/cmcurl/lib/url.c38
-rw-r--r--Utilities/cmcurl/lib/urlapi.c93
-rw-r--r--Utilities/cmcurl/lib/urldata.h16
-rw-r--r--Utilities/cmcurl/lib/version.c4
-rw-r--r--Utilities/cmcurl/lib/vquic/curl_msh3.c5
-rw-r--r--Utilities/cmcurl/lib/vquic/curl_ngtcp2.c429
-rw-r--r--Utilities/cmcurl/lib/vquic/curl_quiche.c52
-rw-r--r--Utilities/cmcurl/lib/vquic/vquic.c6
-rw-r--r--Utilities/cmcurl/lib/vssh/libssh2.c26
-rw-r--r--Utilities/cmcurl/lib/vssh/wolfssh.c2
-rw-r--r--Utilities/cmcurl/lib/vtls/bearssl.c32
-rw-r--r--Utilities/cmcurl/lib/vtls/gskit.c14
-rw-r--r--Utilities/cmcurl/lib/vtls/gtls.c42
-rw-r--r--Utilities/cmcurl/lib/vtls/mbedtls.c32
-rw-r--r--Utilities/cmcurl/lib/vtls/nss.c81
-rw-r--r--Utilities/cmcurl/lib/vtls/openssl.c81
-rw-r--r--Utilities/cmcurl/lib/vtls/rustls.c34
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel.c64
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel.h116
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel_int.h142
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel_verify.c4
-rw-r--r--Utilities/cmcurl/lib/vtls/sectransp.c43
-rw-r--r--Utilities/cmcurl/lib/vtls/vtls.c27
-rw-r--r--Utilities/cmcurl/lib/vtls/vtls_int.h3
-rw-r--r--Utilities/cmcurl/lib/vtls/wolfssl.c73
-rw-r--r--Utilities/cmcurl/lib/warnless.c10
-rw-r--r--Utilities/cmcurl/lib/warnless.h10
-rw-r--r--Utilities/cmcurl/lib/ws.c56
92 files changed, 2461 insertions, 1710 deletions
diff --git a/Utilities/cmcurl/CMake/FindNGTCP2.cmake b/Utilities/cmcurl/CMake/FindNGTCP2.cmake
index ff0d49e..ae92e41 100644
--- a/Utilities/cmcurl/CMake/FindNGTCP2.cmake
+++ b/Utilities/cmcurl/CMake/FindNGTCP2.cmake
@@ -31,7 +31,7 @@ Find the ngtcp2 library
This module accepts optional COMPONENTS to control the crypto library (these are
mutually exclusive)::
- OpenSSL: Use libngtcp2_crypto_openssl
+ OpenSSL: Use libngtcp2_crypto_quictls
GnuTLS: Use libngtcp2_crypto_gnutls
Result Variables
@@ -71,7 +71,7 @@ endif()
if(NGTCP2_FIND_COMPONENTS)
set(NGTCP2_CRYPTO_BACKEND "")
foreach(component IN LISTS NGTCP2_FIND_COMPONENTS)
- if(component MATCHES "^(BoringSSL|OpenSSL|wolfSSL|GnuTLS)")
+ if(component MATCHES "^(BoringSSL|quictls|wolfSSL|GnuTLS)")
if(NGTCP2_CRYPTO_BACKEND)
message(FATAL_ERROR "NGTCP2: Only one crypto library can be selected")
endif()
diff --git a/Utilities/cmcurl/CMakeLists.txt b/Utilities/cmcurl/CMakeLists.txt
index 82f9b0b..ced5af4 100644
--- a/Utilities/cmcurl/CMakeLists.txt
+++ b/Utilities/cmcurl/CMakeLists.txt
@@ -242,6 +242,8 @@ endif()
include_directories(${CURL_SOURCE_DIR}/include)
+set(CMAKE_UNITY_BUILD_BATCH_SIZE 0)
+
option(CURL_WERROR "Turn compiler warnings into errors" OFF)
option(PICKY_COMPILER "Enable picky compiler options" ON)
option(BUILD_CURL_EXE "Set to ON to build curl executable." ON)
@@ -689,7 +691,7 @@ endif()
option(CURL_BROTLI "Set to ON to enable building curl with brotli support." OFF)
set(HAVE_BROTLI OFF)
if(CURL_BROTLI)
- find_package(Brotli QUIET)
+ find_package(Brotli REQUIRED)
if(BROTLI_FOUND)
set(HAVE_BROTLI ON)
list(APPEND CURL_LIBS ${BROTLI_LIBRARIES})
@@ -768,7 +770,7 @@ if(USE_NGTCP2)
elseif(HAVE_BORINGSSL)
find_package(NGTCP2 REQUIRED BoringSSL)
else()
- find_package(NGTCP2 REQUIRED OpenSSL)
+ find_package(NGTCP2 REQUIRED quictls)
endif()
CheckQuicSupportInOpenSSL()
elseif(USE_GNUTLS)
@@ -839,9 +841,7 @@ if(NOT CURL_DISABLE_LDAP)
endif()
# Now that we know, we're not using windows LDAP...
- if(USE_WIN32_LDAP)
- check_include_file_concat("winldap.h" HAVE_WINLDAP_H)
- else()
+ if(NOT USE_WIN32_LDAP)
# Check for LDAP
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_LIBRARIES})
check_library_exists_concat(${CMAKE_LDAP_LIB} ldap_init HAVE_LIBLDAP)
diff --git a/Utilities/cmcurl/include/curl/curl.h b/Utilities/cmcurl/include/curl/curl.h
index cae9b1c..b668dc0 100644
--- a/Utilities/cmcurl/include/curl/curl.h
+++ b/Utilities/cmcurl/include/curl/curl.h
@@ -93,7 +93,7 @@
defined(__CYGWIN__) || defined(AMIGA) || defined(__NuttX__) || \
(defined(__FreeBSD_version) && (__FreeBSD_version < 800000)) || \
(defined(__MidnightBSD_version) && (__MidnightBSD_version < 100000)) || \
- defined(__sun__) || defined(__serenity__)
+ defined(__sun__) || defined(__serenity__) || defined(__vxworks__)
#include <sys/select.h>
#endif
@@ -781,7 +781,7 @@ typedef enum {
CURLPROXY_HTTP_1_0 = 1, /* added in 7.19.4, force to use CONNECT
HTTP/1.0 */
CURLPROXY_HTTPS = 2, /* HTTPS but stick to HTTP/1 added in 7.52.0 */
- CURLPROXY_HTTPS2 = 3, /* HTTPS and attempt HTTP/2 added in 8.1.0 */
+ CURLPROXY_HTTPS2 = 3, /* HTTPS and attempt HTTP/2 added in 8.2.0 */
CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already
in 7.10 */
CURLPROXY_SOCKS5 = 5, /* added in 7.10 */
@@ -2113,7 +2113,7 @@ typedef enum {
CURLOPT(CURLOPT_SASL_AUTHZID, CURLOPTTYPE_STRINGPOINT, 289),
/* allow RCPT TO command to fail for some recipients */
- CURLOPT(CURLOPT_MAIL_RCPT_ALLLOWFAILS, CURLOPTTYPE_LONG, 290),
+ CURLOPT(CURLOPT_MAIL_RCPT_ALLOWFAILS, CURLOPTTYPE_LONG, 290),
/* the private SSL-certificate as a "blob" */
CURLOPT(CURLOPT_SSLCERT_BLOB, CURLOPTTYPE_BLOB, 291),
@@ -2207,6 +2207,9 @@ typedef enum {
/* Can leak things, gonna exit() soon */
CURLOPT(CURLOPT_QUICK_EXIT, CURLOPTTYPE_LONG, 322),
+ /* set a specific client IP for HAProxy PROXY protocol header? */
+ CURLOPT(CURLOPT_HAPROXY_CLIENT_IP, CURLOPTTYPE_STRINGPOINT, 323),
+
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;
@@ -2235,6 +2238,9 @@ typedef enum {
/* */
#define CURLOPT_FTP_RESPONSE_TIMEOUT CURLOPT_SERVER_RESPONSE_TIMEOUT
+/* Added in 8.2.0 */
+#define CURLOPT_MAIL_RCPT_ALLLOWFAILS CURLOPT_MAIL_RCPT_ALLOWFAILS
+
#else
/* This is set if CURL_NO_OLDIES is defined at compile-time */
#undef CURLOPT_DNS_USE_GLOBAL_CACHE /* soon obsolete */
@@ -2918,7 +2924,9 @@ typedef enum {
CURLINFO_REFERER = CURLINFO_STRING + 60,
CURLINFO_CAINFO = CURLINFO_STRING + 61,
CURLINFO_CAPATH = CURLINFO_STRING + 62,
- CURLINFO_LASTONE = 62
+ CURLINFO_XFER_ID = CURLINFO_OFF_T + 63,
+ CURLINFO_CONN_ID = CURLINFO_OFF_T + 64,
+ CURLINFO_LASTONE = 64
} CURLINFO;
/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
diff --git a/Utilities/cmcurl/include/curl/curlver.h b/Utilities/cmcurl/include/curl/curlver.h
index 5588fa5..4c39a6d 100644
--- a/Utilities/cmcurl/include/curl/curlver.h
+++ b/Utilities/cmcurl/include/curl/curlver.h
@@ -32,13 +32,13 @@
/* This is the version number of the libcurl package from which this header
file origins: */
-#define LIBCURL_VERSION "8.1.2"
+#define LIBCURL_VERSION "8.2.1"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 8
-#define LIBCURL_VERSION_MINOR 1
-#define LIBCURL_VERSION_PATCH 2
+#define LIBCURL_VERSION_MINOR 2
+#define LIBCURL_VERSION_PATCH 1
/* This is the numeric version of the libcurl version number, meant for easier
parsing and comparisons by programs. The LIBCURL_VERSION_NUM define will
@@ -59,7 +59,7 @@
CURL_VERSION_BITS() macro since curl's own configure script greps for it
and needs it to contain the full number.
*/
-#define LIBCURL_VERSION_NUM 0x080102
+#define LIBCURL_VERSION_NUM 0x080201
/*
* This is the date and time when the full source package was created. The
diff --git a/Utilities/cmcurl/include/curl/system.h b/Utilities/cmcurl/include/curl/system.h
index def7739..b2640c8 100644
--- a/Utilities/cmcurl/include/curl/system.h
+++ b/Utilities/cmcurl/include/curl/system.h
@@ -237,33 +237,28 @@
# define CURL_PULL_SYS_SOCKET_H 1
#elif defined(__MVS__)
-# if defined(__IBMC__) || defined(__IBMCPP__)
-# if defined(_ILP32)
-# elif defined(_LP64)
-# endif
-# if defined(_LONG_LONG)
-# define CURL_TYPEOF_CURL_OFF_T long long
-# define CURL_FORMAT_CURL_OFF_T "lld"
-# define CURL_FORMAT_CURL_OFF_TU "llu"
-# define CURL_SUFFIX_CURL_OFF_T LL
-# define CURL_SUFFIX_CURL_OFF_TU ULL
-# elif defined(_LP64)
-# define CURL_TYPEOF_CURL_OFF_T long
-# define CURL_FORMAT_CURL_OFF_T "ld"
-# define CURL_FORMAT_CURL_OFF_TU "lu"
-# define CURL_SUFFIX_CURL_OFF_T L
-# define CURL_SUFFIX_CURL_OFF_TU UL
-# else
-# define CURL_TYPEOF_CURL_OFF_T long
-# define CURL_FORMAT_CURL_OFF_T "ld"
-# define CURL_FORMAT_CURL_OFF_TU "lu"
-# define CURL_SUFFIX_CURL_OFF_T L
-# define CURL_SUFFIX_CURL_OFF_TU UL
-# endif
-# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
-# define CURL_PULL_SYS_TYPES_H 1
-# define CURL_PULL_SYS_SOCKET_H 1
+# if defined(_LONG_LONG)
+# define CURL_TYPEOF_CURL_OFF_T long long
+# define CURL_FORMAT_CURL_OFF_T "lld"
+# define CURL_FORMAT_CURL_OFF_TU "llu"
+# define CURL_SUFFIX_CURL_OFF_T LL
+# define CURL_SUFFIX_CURL_OFF_TU ULL
+# elif defined(_LP64)
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
+# else
+# define CURL_TYPEOF_CURL_OFF_T long
+# define CURL_FORMAT_CURL_OFF_T "ld"
+# define CURL_FORMAT_CURL_OFF_TU "lu"
+# define CURL_SUFFIX_CURL_OFF_T L
+# define CURL_SUFFIX_CURL_OFF_TU UL
# endif
+# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+# define CURL_PULL_SYS_TYPES_H 1
+# define CURL_PULL_SYS_SOCKET_H 1
#elif defined(__370__)
# if defined(__IBMC__) || defined(__IBMCPP__)
diff --git a/Utilities/cmcurl/include/curl/typecheck-gcc.h b/Utilities/cmcurl/include/curl/typecheck-gcc.h
index bc8d7a7..b880f3d 100644
--- a/Utilities/cmcurl/include/curl/typecheck-gcc.h
+++ b/Utilities/cmcurl/include/curl/typecheck-gcc.h
@@ -280,6 +280,7 @@ CURLWARNING(_curl_easy_getinfo_err_curl_off_t,
(option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \
(option) == CURLOPT_FTPPORT || \
(option) == CURLOPT_HSTS || \
+ (option) == CURLOPT_HAPROXY_CLIENT_IP || \
(option) == CURLOPT_INTERFACE || \
(option) == CURLOPT_ISSUERCERT || \
(option) == CURLOPT_KEYPASSWD || \
diff --git a/Utilities/cmcurl/include/curl/websockets.h b/Utilities/cmcurl/include/curl/websockets.h
index fd6a916..6ef6a2b 100644
--- a/Utilities/cmcurl/include/curl/websockets.h
+++ b/Utilities/cmcurl/include/curl/websockets.h
@@ -54,13 +54,13 @@ struct curl_ws_frame {
*/
CURL_EXTERN CURLcode curl_ws_recv(CURL *curl, void *buffer, size_t buflen,
size_t *recv,
- struct curl_ws_frame **metap);
+ const struct curl_ws_frame **metap);
-/* sendflags for curl_ws_send() */
+/* flags for curl_ws_send() */
#define CURLWS_PONG (1<<6)
/*
- * NAME curl_easy_send()
+ * NAME curl_ws_send()
*
* DESCRIPTION
*
@@ -69,13 +69,13 @@ CURL_EXTERN CURLcode curl_ws_recv(CURL *curl, void *buffer, size_t buflen,
*/
CURL_EXTERN CURLcode curl_ws_send(CURL *curl, const void *buffer,
size_t buflen, size_t *sent,
- curl_off_t framesize,
- unsigned int sendflags);
+ curl_off_t fragsize,
+ unsigned int flags);
/* bits for the CURLOPT_WS_OPTIONS bitmask: */
#define CURLWS_RAW_MODE (1<<0)
-CURL_EXTERN struct curl_ws_frame *curl_ws_meta(CURL *curl);
+CURL_EXTERN const struct curl_ws_frame *curl_ws_meta(CURL *curl);
#ifdef __cplusplus
}
diff --git a/Utilities/cmcurl/lib/CMakeLists.txt b/Utilities/cmcurl/lib/CMakeLists.txt
index ba75420..20249fe 100644
--- a/Utilities/cmcurl/lib/CMakeLists.txt
+++ b/Utilities/cmcurl/lib/CMakeLists.txt
@@ -90,15 +90,30 @@ add_library(
)
add_library(
+ curlu # special libcurlu library just for unittests
+ STATIC
+ EXCLUDE_FROM_ALL
+ ${HHEADERS} ${CSOURCES}
+)
+target_compile_definitions(curlu PUBLIC UNITTESTS CURL_STATICLIB)
+
+add_library(
${PROJECT_NAME}::${LIB_NAME}
ALIAS ${LIB_NAME}
)
+if(ENABLE_CURLDEBUG)
+ # We must compile memdebug.c separately to avoid memdebug.h redefinitions
+ # being applied to memdebug.c itself.
+ set_source_files_properties(memdebug.c PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON)
+endif()
+
if(NOT BUILD_SHARED_LIBS)
set_target_properties(${LIB_NAME} PROPERTIES INTERFACE_COMPILE_DEFINITIONS CURL_STATICLIB)
endif()
target_link_libraries(${LIB_NAME} PRIVATE ${CURL_LIBS})
+target_link_libraries(curlu PRIVATE ${CURL_LIBS})
if(0) # This code not needed for building within CMake.
transform_makefile_inc("Makefile.soname" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake")
diff --git a/Utilities/cmcurl/lib/Makefile.inc b/Utilities/cmcurl/lib/Makefile.inc
index f815170..cc7d287 100644
--- a/Utilities/cmcurl/lib/Makefile.inc
+++ b/Utilities/cmcurl/lib/Makefile.inc
@@ -72,6 +72,7 @@ LIB_VTLS_HFILES = \
vtls/openssl.h \
vtls/rustls.h \
vtls/schannel.h \
+ vtls/schannel_int.h \
vtls/sectransp.h \
vtls/vtls.h \
vtls/vtls_int.h \
@@ -179,6 +180,7 @@ LIB_CFILES = \
krb5.c \
ldap.c \
llist.c \
+ macos.c \
md4.c \
md5.c \
memdebug.c \
@@ -315,6 +317,7 @@ LIB_HFILES = \
inet_ntop.h \
inet_pton.h \
llist.h \
+ macos.h \
memdebug.h \
mime.h \
mqtt.h \
diff --git a/Utilities/cmcurl/lib/altsvc.c b/Utilities/cmcurl/lib/altsvc.c
index f812baf..11009d5 100644
--- a/Utilities/cmcurl/lib/altsvc.c
+++ b/Utilities/cmcurl/lib/altsvc.c
@@ -424,7 +424,7 @@ static void altsvc_flush(struct altsvcinfo *asi, enum alpnid srcalpnid,
#ifdef DEBUGBUILD
/* to play well with debug builds, we can *set* a fixed time this will
return */
-static time_t debugtime(void *unused)
+static time_t altsvc_debugtime(void *unused)
{
char *timestr = getenv("CURL_TIME");
(void)unused;
@@ -434,7 +434,8 @@ static time_t debugtime(void *unused)
}
return time(NULL);
}
-#define time(x) debugtime(x)
+#undef time
+#define time(x) altsvc_debugtime(x)
#endif
#define ISNEWLINE(x) (((x) == '\n') || (x) == '\r')
diff --git a/Utilities/cmcurl/lib/amigaos.c b/Utilities/cmcurl/lib/amigaos.c
index b0a9500..139309b 100644
--- a/Utilities/cmcurl/lib/amigaos.c
+++ b/Utilities/cmcurl/lib/amigaos.c
@@ -178,6 +178,7 @@ struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
#endif /* CURLRES_AMIGA */
#ifdef USE_AMISSL
+#include <signal.h>
int Curl_amiga_select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *errorfds, struct timeval *timeout)
{
diff --git a/Utilities/cmcurl/lib/base64.c b/Utilities/cmcurl/lib/base64.c
index 971300e..9d495d4 100644
--- a/Utilities/cmcurl/lib/base64.c
+++ b/Utilities/cmcurl/lib/base64.c
@@ -43,7 +43,7 @@
/* ---- Base64 Encoding/Decoding Table --- */
/* Padding character string starts at offset 64. */
-static const char base64[]=
+static const char base64encdec[]=
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
/* The Base 64 encoding with a URL and filename safe alphabet, RFC 4648
@@ -120,7 +120,7 @@ CURLcode Curl_base64_decode(const char *src,
/* replaces
{
unsigned char c;
- const unsigned char *p = (const unsigned char *)base64;
+ const unsigned char *p = (const unsigned char *)base64encdec;
for(c = 0; *p; c++, p++)
lookup[*p] = c;
}
@@ -264,7 +264,7 @@ static CURLcode base64_encode(const char *table64,
CURLcode Curl_base64_encode(const char *inputbuff, size_t insize,
char **outptr, size_t *outlen)
{
- return base64_encode(base64, inputbuff, insize, outptr, outlen);
+ return base64_encode(base64encdec, inputbuff, insize, outptr, outlen);
}
/*
diff --git a/Utilities/cmcurl/lib/bufq.c b/Utilities/cmcurl/lib/bufq.c
index 30598cf..1555449 100644
--- a/Utilities/cmcurl/lib/bufq.c
+++ b/Utilities/cmcurl/lib/bufq.c
@@ -418,7 +418,8 @@ ssize_t Curl_bufq_write(struct bufq *q,
break;
}
n = chunk_append(tail, buf, len);
- DEBUGASSERT(n);
+ if(!n)
+ break;
nwritten += n;
buf += n;
len -= n;
@@ -528,6 +529,14 @@ ssize_t Curl_bufq_pass(struct bufq *q, Curl_bufq_writer *writer,
}
break;
}
+ if(!chunk_written) {
+ if(!nwritten) {
+ /* treat as blocked */
+ *err = CURLE_AGAIN;
+ nwritten = -1;
+ }
+ break;
+ }
Curl_bufq_skip(q, (size_t)chunk_written);
nwritten += chunk_written;
}
@@ -551,7 +560,8 @@ ssize_t Curl_bufq_write_pass(struct bufq *q,
/* real error, fail */
return -1;
}
- /* would block */
+ /* would block, bufq is full, give up */
+ break;
}
}
@@ -562,16 +572,25 @@ ssize_t Curl_bufq_write_pass(struct bufq *q,
/* real error, fail */
return -1;
}
- /* no room in bufq, bail out */
- goto out;
+ /* no room in bufq */
+ break;
}
+ /* edge case of writer returning 0 (and len is >0)
+ * break or we might enter an infinite loop here */
+ if(n == 0)
+ break;
+
/* Maybe only part of `data` has been added, continue to loop */
buf += (size_t)n;
len -= (size_t)n;
nwritten += (size_t)n;
}
-out:
+ if(!nwritten && len) {
+ *err = CURLE_AGAIN;
+ return -1;
+ }
+ *err = CURLE_OK;
return nwritten;
}
diff --git a/Utilities/cmcurl/lib/c-hyper.c b/Utilities/cmcurl/lib/c-hyper.c
index 756aebe..c29983c 100644
--- a/Utilities/cmcurl/lib/c-hyper.c
+++ b/Utilities/cmcurl/lib/c-hyper.c
@@ -71,9 +71,11 @@ size_t Curl_hyper_recv(void *userp, hyper_context *ctx,
DEBUGASSERT(conn);
(void)ctx;
+ DEBUGF(infof(data, "Curl_hyper_recv(%zu)", buflen));
result = Curl_read(data, conn->sockfd, (char *)buf, buflen, &nread);
if(result == CURLE_AGAIN) {
/* would block, register interest */
+ DEBUGF(infof(data, "Curl_hyper_recv(%zu) -> EAGAIN", buflen));
if(data->hyp.read_waker)
hyper_waker_free(data->hyp.read_waker);
data->hyp.read_waker = hyper_context_waker(ctx);
@@ -87,6 +89,7 @@ size_t Curl_hyper_recv(void *userp, hyper_context *ctx,
failf(data, "Curl_read failed");
return HYPER_IO_ERROR;
}
+ DEBUGF(infof(data, "Curl_hyper_recv(%zu) -> %zd", buflen, nread));
return (size_t)nread;
}
@@ -98,8 +101,12 @@ size_t Curl_hyper_send(void *userp, hyper_context *ctx,
CURLcode result;
ssize_t nwrote;
+ DEBUGF(infof(data, "Curl_hyper_send(%zu)", buflen));
result = Curl_write(data, conn->sockfd, (void *)buf, buflen, &nwrote);
+ if(!result && !nwrote)
+ result = CURLE_AGAIN;
if(result == CURLE_AGAIN) {
+ DEBUGF(infof(data, "Curl_hyper_send(%zu) -> EAGAIN", buflen));
/* would block, register interest */
if(data->hyp.write_waker)
hyper_waker_free(data->hyp.write_waker);
@@ -114,6 +121,7 @@ size_t Curl_hyper_send(void *userp, hyper_context *ctx,
failf(data, "Curl_write failed");
return HYPER_IO_ERROR;
}
+ DEBUGF(infof(data, "Curl_hyper_send(%zu) -> %zd", buflen, nwrote));
return (size_t)nwrote;
}
@@ -433,8 +441,7 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
break;
}
else if(t != HYPER_TASK_RESPONSE) {
- *didwhat = KEEP_RECV;
- break;
+ continue;
}
/* HYPER_TASK_RESPONSE */
diff --git a/Utilities/cmcurl/lib/cf-h1-proxy.c b/Utilities/cmcurl/lib/cf-h1-proxy.c
index b42c4e6..c9b157c 100644
--- a/Utilities/cmcurl/lib/cf-h1-proxy.c
+++ b/Utilities/cmcurl/lib/cf-h1-proxy.c
@@ -54,16 +54,16 @@
typedef enum {
- TUNNEL_INIT, /* init/default/no tunnel state */
- TUNNEL_CONNECT, /* CONNECT request is being send */
- TUNNEL_RECEIVE, /* CONNECT answer is being received */
- TUNNEL_RESPONSE, /* CONNECT response received completely */
- TUNNEL_ESTABLISHED,
- TUNNEL_FAILED
-} tunnel_state;
+ H1_TUNNEL_INIT, /* init/default/no tunnel state */
+ H1_TUNNEL_CONNECT, /* CONNECT request is being send */
+ H1_TUNNEL_RECEIVE, /* CONNECT answer is being received */
+ H1_TUNNEL_RESPONSE, /* CONNECT response received completely */
+ H1_TUNNEL_ESTABLISHED,
+ H1_TUNNEL_FAILED
+} h1_tunnel_state;
/* struct for HTTP CONNECT tunneling */
-struct tunnel_state {
+struct h1_tunnel_state {
int sockindex;
const char *hostname;
int remote_port;
@@ -78,23 +78,23 @@ struct tunnel_state {
KEEPON_IGNORE
} keepon;
curl_off_t cl; /* size of content to read and ignore */
- tunnel_state tunnel_state;
+ h1_tunnel_state tunnel_state;
BIT(chunked_encoding);
BIT(close_connection);
};
-static bool tunnel_is_established(struct tunnel_state *ts)
+static bool tunnel_is_established(struct h1_tunnel_state *ts)
{
- return ts && (ts->tunnel_state == TUNNEL_ESTABLISHED);
+ return ts && (ts->tunnel_state == H1_TUNNEL_ESTABLISHED);
}
-static bool tunnel_is_failed(struct tunnel_state *ts)
+static bool tunnel_is_failed(struct h1_tunnel_state *ts)
{
- return ts && (ts->tunnel_state == TUNNEL_FAILED);
+ return ts && (ts->tunnel_state == H1_TUNNEL_FAILED);
}
-static CURLcode tunnel_reinit(struct tunnel_state *ts,
+static CURLcode tunnel_reinit(struct h1_tunnel_state *ts,
struct connectdata *conn,
struct Curl_easy *data)
{
@@ -102,7 +102,7 @@ static CURLcode tunnel_reinit(struct tunnel_state *ts,
DEBUGASSERT(ts);
Curl_dyn_reset(&ts->rcvbuf);
Curl_dyn_reset(&ts->req);
- ts->tunnel_state = TUNNEL_INIT;
+ ts->tunnel_state = H1_TUNNEL_INIT;
ts->keepon = KEEPON_CONNECT;
ts->cl = 0;
ts->close_connection = FALSE;
@@ -124,12 +124,12 @@ static CURLcode tunnel_reinit(struct tunnel_state *ts,
return CURLE_OK;
}
-static CURLcode tunnel_init(struct tunnel_state **pts,
+static CURLcode tunnel_init(struct h1_tunnel_state **pts,
struct Curl_easy *data,
struct connectdata *conn,
int sockindex)
{
- struct tunnel_state *ts;
+ struct h1_tunnel_state *ts;
CURLcode result;
if(conn->handler->flags & PROTOPT_NOTCPPROXY) {
@@ -157,16 +157,16 @@ static CURLcode tunnel_init(struct tunnel_state **pts,
return tunnel_reinit(ts, conn, data);
}
-static void tunnel_go_state(struct Curl_cfilter *cf,
- struct tunnel_state *ts,
- tunnel_state new_state,
- struct Curl_easy *data)
+static void h1_tunnel_go_state(struct Curl_cfilter *cf,
+ struct h1_tunnel_state *ts,
+ h1_tunnel_state new_state,
+ struct Curl_easy *data)
{
if(ts->tunnel_state == new_state)
return;
/* leaving this one */
switch(ts->tunnel_state) {
- case TUNNEL_CONNECT:
+ case H1_TUNNEL_CONNECT:
data->req.ignorebody = FALSE;
break;
default:
@@ -174,36 +174,36 @@ static void tunnel_go_state(struct Curl_cfilter *cf,
}
/* entering this one */
switch(new_state) {
- case TUNNEL_INIT:
+ case H1_TUNNEL_INIT:
DEBUGF(LOG_CF(data, cf, "new tunnel state 'init'"));
tunnel_reinit(ts, cf->conn, data);
break;
- case TUNNEL_CONNECT:
+ case H1_TUNNEL_CONNECT:
DEBUGF(LOG_CF(data, cf, "new tunnel state 'connect'"));
- ts->tunnel_state = TUNNEL_CONNECT;
+ ts->tunnel_state = H1_TUNNEL_CONNECT;
ts->keepon = KEEPON_CONNECT;
Curl_dyn_reset(&ts->rcvbuf);
break;
- case TUNNEL_RECEIVE:
+ case H1_TUNNEL_RECEIVE:
DEBUGF(LOG_CF(data, cf, "new tunnel state 'receive'"));
- ts->tunnel_state = TUNNEL_RECEIVE;
+ ts->tunnel_state = H1_TUNNEL_RECEIVE;
break;
- case TUNNEL_RESPONSE:
+ case H1_TUNNEL_RESPONSE:
DEBUGF(LOG_CF(data, cf, "new tunnel state 'response'"));
- ts->tunnel_state = TUNNEL_RESPONSE;
+ ts->tunnel_state = H1_TUNNEL_RESPONSE;
break;
- case TUNNEL_ESTABLISHED:
+ case H1_TUNNEL_ESTABLISHED:
DEBUGF(LOG_CF(data, cf, "new tunnel state 'established'"));
infof(data, "CONNECT phase completed");
data->state.authproxy.done = TRUE;
data->state.authproxy.multipass = FALSE;
/* FALLTHROUGH */
- case TUNNEL_FAILED:
- if(new_state == TUNNEL_FAILED)
+ case H1_TUNNEL_FAILED:
+ if(new_state == H1_TUNNEL_FAILED)
DEBUGF(LOG_CF(data, cf, "new tunnel state 'failed'"));
ts->tunnel_state = new_state;
Curl_dyn_reset(&ts->rcvbuf);
@@ -225,9 +225,9 @@ static void tunnel_go_state(struct Curl_cfilter *cf,
static void tunnel_free(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
- struct tunnel_state *ts = cf->ctx;
+ struct h1_tunnel_state *ts = cf->ctx;
if(ts) {
- tunnel_go_state(cf, ts, TUNNEL_FAILED, data);
+ h1_tunnel_go_state(cf, ts, H1_TUNNEL_FAILED, data);
Curl_dyn_free(&ts->rcvbuf);
Curl_dyn_free(&ts->req);
free(ts);
@@ -270,7 +270,7 @@ static CURLcode CONNECT_host(struct Curl_easy *data,
#ifndef USE_HYPER
static CURLcode start_CONNECT(struct Curl_cfilter *cf,
struct Curl_easy *data,
- struct tunnel_state *ts)
+ struct h1_tunnel_state *ts)
{
struct connectdata *conn = cf->conn;
char *hostheader = NULL;
@@ -351,7 +351,7 @@ out:
static CURLcode send_CONNECT(struct Curl_easy *data,
struct connectdata *conn,
- struct tunnel_state *ts,
+ struct h1_tunnel_state *ts,
bool *done)
{
struct SingleRequest *k = &data->req;
@@ -399,7 +399,7 @@ out:
static CURLcode on_resp_header(struct Curl_cfilter *cf,
struct Curl_easy *data,
- struct tunnel_state *ts,
+ struct h1_tunnel_state *ts,
const char *header)
{
CURLcode result = CURLE_OK;
@@ -475,7 +475,7 @@ static CURLcode on_resp_header(struct Curl_cfilter *cf,
static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
struct Curl_easy *data,
- struct tunnel_state *ts,
+ struct h1_tunnel_state *ts,
bool *done)
{
CURLcode result = CURLE_OK;
@@ -671,7 +671,7 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
/* The Hyper version of CONNECT */
static CURLcode start_CONNECT(struct Curl_cfilter *cf,
struct Curl_easy *data,
- struct tunnel_state *ts)
+ struct h1_tunnel_state *ts)
{
struct connectdata *conn = cf->conn;
struct hyptransfer *h = &data->hyp;
@@ -882,7 +882,7 @@ error:
static CURLcode send_CONNECT(struct Curl_easy *data,
struct connectdata *conn,
- struct tunnel_state *ts,
+ struct h1_tunnel_state *ts,
bool *done)
{
struct hyptransfer *h = &data->hyp;
@@ -919,7 +919,7 @@ error:
static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
struct Curl_easy *data,
- struct tunnel_state *ts,
+ struct h1_tunnel_state *ts,
bool *done)
{
struct hyptransfer *h = &data->hyp;
@@ -949,9 +949,9 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf,
#endif /* USE_HYPER */
-static CURLcode CONNECT(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- struct tunnel_state *ts)
+static CURLcode H1_CONNECT(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct h1_tunnel_state *ts)
{
struct connectdata *conn = cf->conn;
CURLcode result;
@@ -973,25 +973,25 @@ static CURLcode CONNECT(struct Curl_cfilter *cf,
}
switch(ts->tunnel_state) {
- case TUNNEL_INIT:
+ case H1_TUNNEL_INIT:
/* Prepare the CONNECT request and make a first attempt to send. */
DEBUGF(LOG_CF(data, cf, "CONNECT start"));
result = start_CONNECT(cf, data, ts);
if(result)
goto out;
- tunnel_go_state(cf, ts, TUNNEL_CONNECT, data);
+ h1_tunnel_go_state(cf, ts, H1_TUNNEL_CONNECT, data);
/* FALLTHROUGH */
- case TUNNEL_CONNECT:
+ case H1_TUNNEL_CONNECT:
/* see that the request is completely sent */
DEBUGF(LOG_CF(data, cf, "CONNECT send"));
result = send_CONNECT(data, cf->conn, ts, &done);
if(result || !done)
goto out;
- tunnel_go_state(cf, ts, TUNNEL_RECEIVE, data);
+ h1_tunnel_go_state(cf, ts, H1_TUNNEL_RECEIVE, data);
/* FALLTHROUGH */
- case TUNNEL_RECEIVE:
+ case H1_TUNNEL_RECEIVE:
/* read what is there */
DEBUGF(LOG_CF(data, cf, "CONNECT receive"));
result = recv_CONNECT_resp(cf, data, ts, &done);
@@ -1003,10 +1003,10 @@ static CURLcode CONNECT(struct Curl_cfilter *cf,
if(result || !done)
goto out;
/* got it */
- tunnel_go_state(cf, ts, TUNNEL_RESPONSE, data);
+ h1_tunnel_go_state(cf, ts, H1_TUNNEL_RESPONSE, data);
/* FALLTHROUGH */
- case TUNNEL_RESPONSE:
+ case H1_TUNNEL_RESPONSE:
DEBUGF(LOG_CF(data, cf, "CONNECT response"));
if(data->req.newurl) {
/* not the "final" response, we need to do a follow up request.
@@ -1028,7 +1028,7 @@ static CURLcode CONNECT(struct Curl_cfilter *cf,
}
else {
/* staying on this connection, reset state */
- tunnel_go_state(cf, ts, TUNNEL_INIT, data);
+ h1_tunnel_go_state(cf, ts, H1_TUNNEL_INIT, data);
}
}
break;
@@ -1039,25 +1039,25 @@ static CURLcode CONNECT(struct Curl_cfilter *cf,
} while(data->req.newurl);
- DEBUGASSERT(ts->tunnel_state == TUNNEL_RESPONSE);
+ DEBUGASSERT(ts->tunnel_state == H1_TUNNEL_RESPONSE);
if(data->info.httpproxycode/100 != 2) {
/* a non-2xx response and we have no next url to try. */
Curl_safefree(data->req.newurl);
/* failure, close this connection to avoid re-use */
streamclose(conn, "proxy CONNECT failure");
- tunnel_go_state(cf, ts, TUNNEL_FAILED, data);
+ h1_tunnel_go_state(cf, ts, H1_TUNNEL_FAILED, data);
failf(data, "CONNECT tunnel failed, response %d", data->req.httpcode);
return CURLE_RECV_ERROR;
}
/* 2xx response, SUCCESS! */
- tunnel_go_state(cf, ts, TUNNEL_ESTABLISHED, data);
+ h1_tunnel_go_state(cf, ts, H1_TUNNEL_ESTABLISHED, data);
infof(data, "CONNECT tunnel established, response %d",
data->info.httpproxycode);
result = CURLE_OK;
out:
if(result)
- tunnel_go_state(cf, ts, TUNNEL_FAILED, data);
+ h1_tunnel_go_state(cf, ts, H1_TUNNEL_FAILED, data);
return result;
}
@@ -1066,7 +1066,7 @@ static CURLcode cf_h1_proxy_connect(struct Curl_cfilter *cf,
bool blocking, bool *done)
{
CURLcode result;
- struct tunnel_state *ts = cf->ctx;
+ struct h1_tunnel_state *ts = cf->ctx;
if(cf->connected) {
*done = TRUE;
@@ -1074,7 +1074,7 @@ static CURLcode cf_h1_proxy_connect(struct Curl_cfilter *cf,
}
DEBUGF(LOG_CF(data, cf, "connect"));
- result = cf->next->cft->connect(cf->next, data, blocking, done);
+ result = cf->next->cft->do_connect(cf->next, data, blocking, done);
if(result || !*done)
return result;
@@ -1089,7 +1089,7 @@ static CURLcode cf_h1_proxy_connect(struct Curl_cfilter *cf,
/* TODO: can we do blocking? */
/* We want "seamless" operations through HTTP proxy tunnel */
- result = CONNECT(cf, data, ts);
+ result = H1_CONNECT(cf, data, ts);
if(result)
goto out;
Curl_safefree(data->state.aptr.proxyuserpwd);
@@ -1107,7 +1107,7 @@ static int cf_h1_proxy_get_select_socks(struct Curl_cfilter *cf,
struct Curl_easy *data,
curl_socket_t *socks)
{
- struct tunnel_state *ts = cf->ctx;
+ struct h1_tunnel_state *ts = cf->ctx;
int fds;
fds = cf->next->cft->get_select_socks(cf->next, data, socks);
@@ -1143,10 +1143,10 @@ static void cf_h1_proxy_close(struct Curl_cfilter *cf,
DEBUGF(LOG_CF(data, cf, "close"));
cf->connected = FALSE;
if(cf->ctx) {
- tunnel_go_state(cf, cf->ctx, TUNNEL_INIT, data);
+ h1_tunnel_go_state(cf, cf->ctx, H1_TUNNEL_INIT, data);
}
if(cf->next)
- cf->next->cft->close(cf->next, data);
+ cf->next->cft->do_close(cf->next, data);
}
diff --git a/Utilities/cmcurl/lib/cf-h2-proxy.c b/Utilities/cmcurl/lib/cf-h2-proxy.c
index 8e76ff8..f6acfc5 100644
--- a/Utilities/cmcurl/lib/cf-h2-proxy.c
+++ b/Utilities/cmcurl/lib/cf-h2-proxy.c
@@ -44,26 +44,25 @@
#include "curl_memory.h"
#include "memdebug.h"
-#define H2_NW_CHUNK_SIZE (128*1024)
-#define H2_NW_RECV_CHUNKS 1
-#define H2_NW_SEND_CHUNKS 1
+#define H2_CHUNK_SIZE (16*1024)
-#define HTTP2_HUGE_WINDOW_SIZE (32 * 1024 * 1024) /* 32 MB */
+#define PROXY_HTTP2_HUGE_WINDOW_SIZE (100 * 1024 * 1024)
+#define H2_TUNNEL_WINDOW_SIZE (10 * 1024 * 1024)
+
+#define PROXY_H2_NW_RECV_CHUNKS (H2_TUNNEL_WINDOW_SIZE / H2_CHUNK_SIZE)
+#define PROXY_H2_NW_SEND_CHUNKS 1
+
+#define H2_TUNNEL_RECV_CHUNKS (H2_TUNNEL_WINDOW_SIZE / H2_CHUNK_SIZE)
+#define H2_TUNNEL_SEND_CHUNKS ((128 * 1024) / H2_CHUNK_SIZE)
-#define H2_TUNNEL_WINDOW_SIZE (1024 * 1024)
-#define H2_TUNNEL_CHUNK_SIZE (32 * 1024)
-#define H2_TUNNEL_RECV_CHUNKS \
- (H2_TUNNEL_WINDOW_SIZE / H2_TUNNEL_CHUNK_SIZE)
-#define H2_TUNNEL_SEND_CHUNKS \
- (H2_TUNNEL_WINDOW_SIZE / H2_TUNNEL_CHUNK_SIZE)
typedef enum {
- TUNNEL_INIT, /* init/default/no tunnel state */
- TUNNEL_CONNECT, /* CONNECT request is being send */
- TUNNEL_RESPONSE, /* CONNECT response received completely */
- TUNNEL_ESTABLISHED,
- TUNNEL_FAILED
-} tunnel_state;
+ H2_TUNNEL_INIT, /* init/default/no tunnel state */
+ H2_TUNNEL_CONNECT, /* CONNECT request is being send */
+ H2_TUNNEL_RESPONSE, /* CONNECT response received completely */
+ H2_TUNNEL_ESTABLISHED,
+ H2_TUNNEL_FAILED
+} h2_tunnel_state;
struct tunnel_stream {
struct http_resp *resp;
@@ -72,10 +71,11 @@ struct tunnel_stream {
char *authority;
int32_t stream_id;
uint32_t error;
- tunnel_state state;
- bool has_final_response;
- bool closed;
- bool reset;
+ size_t upload_blocked_len;
+ h2_tunnel_state state;
+ BIT(has_final_response);
+ BIT(closed);
+ BIT(reset);
};
static CURLcode tunnel_stream_init(struct Curl_cfilter *cf,
@@ -85,11 +85,11 @@ static CURLcode tunnel_stream_init(struct Curl_cfilter *cf,
int port;
bool ipv6_ip = cf->conn->bits.ipv6_ip;
- ts->state = TUNNEL_INIT;
+ ts->state = H2_TUNNEL_INIT;
ts->stream_id = -1;
- Curl_bufq_init2(&ts->recvbuf, H2_TUNNEL_CHUNK_SIZE, H2_TUNNEL_RECV_CHUNKS,
+ Curl_bufq_init2(&ts->recvbuf, H2_CHUNK_SIZE, H2_TUNNEL_RECV_CHUNKS,
BUFQ_OPT_SOFT_LIMIT);
- Curl_bufq_init(&ts->sendbuf, H2_TUNNEL_CHUNK_SIZE, H2_TUNNEL_SEND_CHUNKS);
+ Curl_bufq_init(&ts->sendbuf, H2_CHUNK_SIZE, H2_TUNNEL_SEND_CHUNKS);
if(cf->conn->bits.conn_to_host)
hostname = cf->conn->conn_to_host.name;
@@ -123,13 +123,13 @@ static void tunnel_stream_clear(struct tunnel_stream *ts)
Curl_bufq_free(&ts->sendbuf);
Curl_safefree(ts->authority);
memset(ts, 0, sizeof(*ts));
- ts->state = TUNNEL_INIT;
+ ts->state = H2_TUNNEL_INIT;
}
-static void tunnel_go_state(struct Curl_cfilter *cf,
- struct tunnel_stream *ts,
- tunnel_state new_state,
- struct Curl_easy *data)
+static void h2_tunnel_go_state(struct Curl_cfilter *cf,
+ struct tunnel_stream *ts,
+ h2_tunnel_state new_state,
+ struct Curl_easy *data)
{
(void)cf;
@@ -137,7 +137,7 @@ static void tunnel_go_state(struct Curl_cfilter *cf,
return;
/* leaving this one */
switch(ts->state) {
- case TUNNEL_CONNECT:
+ case H2_TUNNEL_CONNECT:
data->req.ignorebody = FALSE;
break;
default:
@@ -145,29 +145,29 @@ static void tunnel_go_state(struct Curl_cfilter *cf,
}
/* entering this one */
switch(new_state) {
- case TUNNEL_INIT:
+ case H2_TUNNEL_INIT:
DEBUGF(LOG_CF(data, cf, "new tunnel state 'init'"));
tunnel_stream_clear(ts);
break;
- case TUNNEL_CONNECT:
+ case H2_TUNNEL_CONNECT:
DEBUGF(LOG_CF(data, cf, "new tunnel state 'connect'"));
- ts->state = TUNNEL_CONNECT;
+ ts->state = H2_TUNNEL_CONNECT;
break;
- case TUNNEL_RESPONSE:
+ case H2_TUNNEL_RESPONSE:
DEBUGF(LOG_CF(data, cf, "new tunnel state 'response'"));
- ts->state = TUNNEL_RESPONSE;
+ ts->state = H2_TUNNEL_RESPONSE;
break;
- case TUNNEL_ESTABLISHED:
+ case H2_TUNNEL_ESTABLISHED:
DEBUGF(LOG_CF(data, cf, "new tunnel state 'established'"));
infof(data, "CONNECT phase completed");
data->state.authproxy.done = TRUE;
data->state.authproxy.multipass = FALSE;
/* FALLTHROUGH */
- case TUNNEL_FAILED:
- if(new_state == TUNNEL_FAILED)
+ case H2_TUNNEL_FAILED:
+ if(new_state == H2_TUNNEL_FAILED)
DEBUGF(LOG_CF(data, cf, "new tunnel state 'failed'"));
ts->state = new_state;
/* If a proxy-authorization header was used for the proxy, then we should
@@ -191,9 +191,11 @@ struct cf_h2_proxy_ctx {
int32_t last_stream_id;
BIT(conn_closed);
BIT(goaway);
+ BIT(nw_out_blocked);
};
/* How to access `call_data` from a cf_h2 filter */
+#undef CF_CTX_CALL_DATA
#define CF_CTX_CALL_DATA(cf) \
((struct cf_h2_proxy_ctx *)(cf)->ctx)->call_data
@@ -219,35 +221,54 @@ static void cf_h2_proxy_ctx_free(struct cf_h2_proxy_ctx *ctx)
}
}
-static ssize_t nw_in_reader(void *reader_ctx,
- unsigned char *buf, size_t buflen,
- CURLcode *err)
+static void drain_tunnel(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct tunnel_stream *tunnel)
+{
+ unsigned char bits;
+
+ (void)cf;
+ bits = CURL_CSELECT_IN;
+ if(!tunnel->closed && !tunnel->reset && tunnel->upload_blocked_len)
+ bits |= CURL_CSELECT_OUT;
+ if(data->state.dselect_bits != bits) {
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] DRAIN dselect_bits=%x",
+ tunnel->stream_id, bits));
+ data->state.dselect_bits = bits;
+ Curl_expire(data, 0, EXPIRE_RUN_NOW);
+ }
+}
+
+static ssize_t proxy_nw_in_reader(void *reader_ctx,
+ unsigned char *buf, size_t buflen,
+ CURLcode *err)
{
struct Curl_cfilter *cf = reader_ctx;
struct Curl_easy *data = CF_DATA_CURRENT(cf);
ssize_t nread;
nread = Curl_conn_cf_recv(cf->next, data, (char *)buf, buflen, err);
- DEBUGF(LOG_CF(data, cf, "nw_in recv(len=%zu) -> %zd, %d",
+ DEBUGF(LOG_CF(data, cf, "nw_in_reader(len=%zu) -> %zd, %d",
buflen, nread, *err));
return nread;
}
-static ssize_t nw_out_writer(void *writer_ctx,
- const unsigned char *buf, size_t buflen,
- CURLcode *err)
+static ssize_t proxy_h2_nw_out_writer(void *writer_ctx,
+ const unsigned char *buf, size_t buflen,
+ CURLcode *err)
{
struct Curl_cfilter *cf = writer_ctx;
struct Curl_easy *data = CF_DATA_CURRENT(cf);
ssize_t nwritten;
nwritten = Curl_conn_cf_send(cf->next, data, (const char *)buf, buflen, err);
- DEBUGF(LOG_CF(data, cf, "nw_out send(len=%zu) -> %zd", buflen, nwritten));
+ DEBUGF(LOG_CF(data, cf, "nw_out_writer(len=%zu) -> %zd, %d",
+ buflen, nwritten, *err));
return nwritten;
}
-static int h2_client_new(struct Curl_cfilter *cf,
- nghttp2_session_callbacks *cbs)
+static int proxy_h2_client_new(struct Curl_cfilter *cf,
+ nghttp2_session_callbacks *cbs)
{
struct cf_h2_proxy_ctx *ctx = cf->ctx;
nghttp2_option *o;
@@ -271,15 +292,18 @@ static int h2_client_new(struct Curl_cfilter *cf,
static ssize_t on_session_send(nghttp2_session *h2,
const uint8_t *buf, size_t blen,
int flags, void *userp);
-static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
- void *userp);
-static int on_stream_close(nghttp2_session *session, int32_t stream_id,
- uint32_t error_code, void *userp);
-static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
- const uint8_t *name, size_t namelen,
- const uint8_t *value, size_t valuelen,
- uint8_t flags,
- void *userp);
+static int proxy_h2_on_frame_recv(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ void *userp);
+static int proxy_h2_on_stream_close(nghttp2_session *session,
+ int32_t stream_id,
+ uint32_t error_code, void *userp);
+static int proxy_h2_on_header(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ const uint8_t *name, size_t namelen,
+ const uint8_t *value, size_t valuelen,
+ uint8_t flags,
+ void *userp);
static int tunnel_recv_callback(nghttp2_session *session, uint8_t flags,
int32_t stream_id,
const uint8_t *mem, size_t len, void *userp);
@@ -298,8 +322,8 @@ static CURLcode cf_h2_proxy_ctx_init(struct Curl_cfilter *cf,
DEBUGASSERT(!ctx->h2);
memset(&ctx->tunnel, 0, sizeof(ctx->tunnel));
- Curl_bufq_init(&ctx->inbufq, H2_NW_CHUNK_SIZE, H2_NW_RECV_CHUNKS);
- Curl_bufq_init(&ctx->outbufq, H2_NW_CHUNK_SIZE, H2_NW_SEND_CHUNKS);
+ Curl_bufq_init(&ctx->inbufq, H2_CHUNK_SIZE, PROXY_H2_NW_RECV_CHUNKS);
+ Curl_bufq_init(&ctx->outbufq, H2_CHUNK_SIZE, PROXY_H2_NW_SEND_CHUNKS);
if(tunnel_stream_init(cf, &ctx->tunnel))
goto out;
@@ -311,14 +335,16 @@ static CURLcode cf_h2_proxy_ctx_init(struct Curl_cfilter *cf,
}
nghttp2_session_callbacks_set_send_callback(cbs, on_session_send);
- nghttp2_session_callbacks_set_on_frame_recv_callback(cbs, on_frame_recv);
+ nghttp2_session_callbacks_set_on_frame_recv_callback(
+ cbs, proxy_h2_on_frame_recv);
nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
cbs, tunnel_recv_callback);
- nghttp2_session_callbacks_set_on_stream_close_callback(cbs, on_stream_close);
- nghttp2_session_callbacks_set_on_header_callback(cbs, on_header);
+ nghttp2_session_callbacks_set_on_stream_close_callback(
+ cbs, proxy_h2_on_stream_close);
+ nghttp2_session_callbacks_set_on_header_callback(cbs, proxy_h2_on_header);
/* The nghttp2 session is not yet setup, do it */
- rc = h2_client_new(cf, cbs);
+ rc = proxy_h2_client_new(cf, cbs);
if(rc) {
failf(data, "Couldn't initialize nghttp2");
goto out;
@@ -343,7 +369,7 @@ static CURLcode cf_h2_proxy_ctx_init(struct Curl_cfilter *cf,
}
rc = nghttp2_session_set_local_window_size(ctx->h2, NGHTTP2_FLAG_NONE, 0,
- HTTP2_HUGE_WINDOW_SIZE);
+ PROXY_HTTP2_HUGE_WINDOW_SIZE);
if(rc) {
failf(data, "nghttp2_session_set_local_window_size() failed: %s(%d)",
nghttp2_strerror(rc), rc);
@@ -362,27 +388,35 @@ out:
return result;
}
-static CURLcode nw_out_flush(struct Curl_cfilter *cf,
- struct Curl_easy *data)
+static int should_close_session(struct cf_h2_proxy_ctx *ctx)
+{
+ return !nghttp2_session_want_read(ctx->h2) &&
+ !nghttp2_session_want_write(ctx->h2);
+}
+
+static CURLcode proxy_h2_nw_out_flush(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
struct cf_h2_proxy_ctx *ctx = cf->ctx;
- size_t buflen = Curl_bufq_len(&ctx->outbufq);
ssize_t nwritten;
CURLcode result;
(void)data;
- if(!buflen)
+ if(Curl_bufq_is_empty(&ctx->outbufq))
return CURLE_OK;
- DEBUGF(LOG_CF(data, cf, "h2 conn flush %zu bytes", buflen));
- nwritten = Curl_bufq_pass(&ctx->outbufq, nw_out_writer, cf, &result);
+ nwritten = Curl_bufq_pass(&ctx->outbufq, proxy_h2_nw_out_writer, cf,
+ &result);
if(nwritten < 0) {
+ if(result == CURLE_AGAIN) {
+ DEBUGF(LOG_CF(data, cf, "flush nw send buffer(%zu) -> EAGAIN",
+ Curl_bufq_len(&ctx->outbufq)));
+ ctx->nw_out_blocked = 1;
+ }
return result;
}
- if((size_t)nwritten < buflen) {
- return CURLE_AGAIN;
- }
- return CURLE_OK;
+ DEBUGF(LOG_CF(data, cf, "nw send buffer flushed"));
+ return Curl_bufq_is_empty(&ctx->outbufq)? CURLE_OK: CURLE_AGAIN;
}
/*
@@ -390,9 +424,9 @@ static CURLcode nw_out_flush(struct Curl_cfilter *cf,
* This function returns 0 if it succeeds, or -1 and error code will
* be assigned to *err.
*/
-static int h2_process_pending_input(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- CURLcode *err)
+static int proxy_h2_process_pending_input(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ CURLcode *err)
{
struct cf_h2_proxy_ctx *ctx = cf->ctx;
const unsigned char *buf;
@@ -422,19 +456,11 @@ static int h2_process_pending_input(struct Curl_cfilter *cf,
}
}
- if(nghttp2_session_check_request_allowed(ctx->h2) == 0) {
- /* 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(cf->conn, "http/2: No new requests allowed");
- }
-
return 0;
}
-static CURLcode h2_progress_ingress(struct Curl_cfilter *cf,
- struct Curl_easy *data)
+static CURLcode proxy_h2_progress_ingress(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
struct cf_h2_proxy_ctx *ctx = cf->ctx;
CURLcode result = CURLE_OK;
@@ -442,9 +468,9 @@ static CURLcode h2_progress_ingress(struct Curl_cfilter *cf,
/* Process network input buffer fist */
if(!Curl_bufq_is_empty(&ctx->inbufq)) {
- DEBUGF(LOG_CF(data, cf, "Process %zd bytes in connection buffer",
+ DEBUGF(LOG_CF(data, cf, "Process %zu bytes in connection buffer",
Curl_bufq_len(&ctx->inbufq)));
- if(h2_process_pending_input(cf, data, &result) < 0)
+ if(proxy_h2_process_pending_input(cf, data, &result) < 0)
return result;
}
@@ -455,8 +481,8 @@ static CURLcode h2_progress_ingress(struct Curl_cfilter *cf,
Curl_bufq_is_empty(&ctx->inbufq) && /* and we consumed our input */
!Curl_bufq_is_full(&ctx->tunnel.recvbuf)) {
- nread = Curl_bufq_slurp(&ctx->inbufq, nw_in_reader, cf, &result);
- DEBUGF(LOG_CF(data, cf, "read %zd bytes nw data -> %zd, %d",
+ nread = Curl_bufq_slurp(&ctx->inbufq, proxy_nw_in_reader, cf, &result);
+ DEBUGF(LOG_CF(data, cf, "read %zu bytes nw data -> %zd, %d",
Curl_bufq_len(&ctx->inbufq), nread, result));
if(nread < 0) {
if(result != CURLE_AGAIN) {
@@ -470,7 +496,7 @@ static CURLcode h2_progress_ingress(struct Curl_cfilter *cf,
break;
}
- if(h2_process_pending_input(cf, data, &result))
+ if(proxy_h2_process_pending_input(cf, data, &result))
return result;
}
@@ -481,25 +507,22 @@ static CURLcode h2_progress_ingress(struct Curl_cfilter *cf,
return CURLE_OK;
}
-/*
- * Check if there's been an update in the priority /
- * dependency settings and if so it submits a PRIORITY frame with the updated
- * info.
- * Flush any out data pending in the network buffer.
- */
-static CURLcode h2_progress_egress(struct Curl_cfilter *cf,
- struct Curl_easy *data)
+static CURLcode proxy_h2_progress_egress(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
struct cf_h2_proxy_ctx *ctx = cf->ctx;
int rv = 0;
- rv = nghttp2_session_send(ctx->h2);
+ ctx->nw_out_blocked = 0;
+ while(!rv && !ctx->nw_out_blocked && nghttp2_session_want_write(ctx->h2))
+ rv = nghttp2_session_send(ctx->h2);
+
if(nghttp2_is_fatal(rv)) {
DEBUGF(LOG_CF(data, cf, "nghttp2_session_send error (%s)%d",
nghttp2_strerror(rv), rv));
return CURLE_SEND_ERROR;
}
- return nw_out_flush(cf, data);
+ return proxy_h2_nw_out_flush(cf, data);
}
static ssize_t on_session_send(nghttp2_session *h2,
@@ -517,7 +540,7 @@ static ssize_t on_session_send(nghttp2_session *h2,
DEBUGASSERT(data);
nwritten = Curl_bufq_write_pass(&ctx->outbufq, buf, blen,
- nw_out_writer, cf, &result);
+ proxy_h2_nw_out_writer, cf, &result);
if(nwritten < 0) {
if(result == CURLE_AGAIN) {
return NGHTTP2_ERR_WOULDBLOCK;
@@ -532,8 +555,9 @@ static ssize_t on_session_send(nghttp2_session *h2,
return nwritten;
}
-static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
- void *userp)
+static int proxy_h2_on_frame_recv(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ void *userp)
{
struct Curl_cfilter *cf = userp;
struct cf_h2_proxy_ctx *ctx = cf->ctx;
@@ -616,11 +640,12 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
return 0;
}
-static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
- const uint8_t *name, size_t namelen,
- const uint8_t *value, size_t valuelen,
- uint8_t flags,
- void *userp)
+static int proxy_h2_on_header(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ const uint8_t *name, size_t namelen,
+ const uint8_t *value, size_t valuelen,
+ uint8_t flags,
+ void *userp)
{
struct Curl_cfilter *cf = userp;
struct cf_h2_proxy_ctx *ctx = cf->ctx;
@@ -752,8 +777,9 @@ static int tunnel_recv_callback(nghttp2_session *session, uint8_t flags,
return 0;
}
-static int on_stream_close(nghttp2_session *session, int32_t stream_id,
- uint32_t error_code, void *userp)
+static int proxy_h2_on_stream_close(nghttp2_session *session,
+ int32_t stream_id,
+ uint32_t error_code, void *userp)
{
struct Curl_cfilter *cf = userp;
struct cf_h2_proxy_ctx *ctx = cf->ctx;
@@ -765,7 +791,7 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
if(stream_id != ctx->tunnel.stream_id)
return 0;
- DEBUGF(LOG_CF(data, cf, "[h2sid=%u] on_stream_close, %s (err %d)",
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%u] proxy_h2_on_stream_close, %s (err %d)",
stream_id, nghttp2_http2_strerror(error_code), error_code));
ctx->tunnel.closed = TRUE;
ctx->tunnel.error = error_code;
@@ -773,15 +799,15 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
return 0;
}
-static CURLcode h2_submit(int32_t *pstream_id,
- struct Curl_cfilter *cf,
- struct Curl_easy *data,
- nghttp2_session *h2,
- struct httpreq *req,
- const nghttp2_priority_spec *pri_spec,
- void *stream_user_data,
- nghttp2_data_source_read_callback read_callback,
- void *read_ctx)
+static CURLcode proxy_h2_submit(int32_t *pstream_id,
+ struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ nghttp2_session *h2,
+ struct httpreq *req,
+ const nghttp2_priority_spec *pri_spec,
+ void *stream_user_data,
+ nghttp2_data_source_read_callback read_callback,
+ void *read_ctx)
{
struct dynhds h2_headers;
nghttp2_nv *nva = NULL;
@@ -881,8 +907,8 @@ static CURLcode submit_CONNECT(struct Curl_cfilter *cf,
if(result)
goto out;
- result = h2_submit(&ts->stream_id, cf, data, ctx->h2, req,
- NULL, ts, tunnel_send_callback, cf);
+ result = proxy_h2_submit(&ts->stream_id, cf, data, ctx->h2, req,
+ NULL, ts, tunnel_send_callback, cf);
if(result) {
DEBUGF(LOG_CF(data, cf, "send: nghttp2_submit_request error (%s)%u",
nghttp2_strerror(ts->stream_id), ts->stream_id));
@@ -907,7 +933,7 @@ static CURLcode inspect_response(struct Curl_cfilter *cf,
DEBUGASSERT(ts->resp);
if(ts->resp->status/100 == 2) {
infof(data, "CONNECT tunnel established, response %d", ts->resp->status);
- tunnel_go_state(cf, ts, TUNNEL_ESTABLISHED, data);
+ h2_tunnel_go_state(cf, ts, H2_TUNNEL_ESTABLISHED, data);
return CURLE_OK;
}
@@ -928,7 +954,7 @@ static CURLcode inspect_response(struct Curl_cfilter *cf,
if(data->req.newurl) {
/* Inidicator that we should try again */
Curl_safefree(data->req.newurl);
- tunnel_go_state(cf, ts, TUNNEL_INIT, data);
+ h2_tunnel_go_state(cf, ts, H2_TUNNEL_INIT, data);
return CURLE_OK;
}
}
@@ -937,9 +963,9 @@ static CURLcode inspect_response(struct Curl_cfilter *cf,
return CURLE_RECV_ERROR;
}
-static CURLcode CONNECT(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- struct tunnel_stream *ts)
+static CURLcode H2_CONNECT(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct tunnel_stream *ts)
{
struct cf_h2_proxy_ctx *ctx = cf->ctx;
CURLcode result = CURLE_OK;
@@ -948,27 +974,27 @@ static CURLcode CONNECT(struct Curl_cfilter *cf,
DEBUGASSERT(ts->authority);
do {
switch(ts->state) {
- case TUNNEL_INIT:
+ case H2_TUNNEL_INIT:
/* Prepare the CONNECT request and make a first attempt to send. */
DEBUGF(LOG_CF(data, cf, "CONNECT start for %s", ts->authority));
result = submit_CONNECT(cf, data, ts);
if(result)
goto out;
- tunnel_go_state(cf, ts, TUNNEL_CONNECT, data);
+ h2_tunnel_go_state(cf, ts, H2_TUNNEL_CONNECT, data);
/* FALLTHROUGH */
- case TUNNEL_CONNECT:
+ case H2_TUNNEL_CONNECT:
/* see that the request is completely sent */
- result = h2_progress_ingress(cf, data);
+ result = proxy_h2_progress_ingress(cf, data);
if(!result)
- result = h2_progress_egress(cf, data);
- if(result) {
- tunnel_go_state(cf, ts, TUNNEL_FAILED, data);
+ result = proxy_h2_progress_egress(cf, data);
+ if(result && result != CURLE_AGAIN) {
+ h2_tunnel_go_state(cf, ts, H2_TUNNEL_FAILED, data);
break;
}
if(ts->has_final_response) {
- tunnel_go_state(cf, ts, TUNNEL_RESPONSE, data);
+ h2_tunnel_go_state(cf, ts, H2_TUNNEL_RESPONSE, data);
}
else {
result = CURLE_OK;
@@ -976,28 +1002,28 @@ static CURLcode CONNECT(struct Curl_cfilter *cf,
}
/* FALLTHROUGH */
- case TUNNEL_RESPONSE:
+ case H2_TUNNEL_RESPONSE:
DEBUGASSERT(ts->has_final_response);
result = inspect_response(cf, data, ts);
if(result)
goto out;
break;
- case TUNNEL_ESTABLISHED:
+ case H2_TUNNEL_ESTABLISHED:
return CURLE_OK;
- case TUNNEL_FAILED:
+ case H2_TUNNEL_FAILED:
return CURLE_RECV_ERROR;
default:
break;
}
- } while(ts->state == TUNNEL_INIT);
+ } while(ts->state == H2_TUNNEL_INIT);
out:
if(result || ctx->tunnel.closed)
- tunnel_go_state(cf, ts, TUNNEL_FAILED, data);
+ h2_tunnel_go_state(cf, ts, H2_TUNNEL_FAILED, data);
return result;
}
@@ -1043,10 +1069,10 @@ static CURLcode cf_h2_proxy_connect(struct Curl_cfilter *cf,
/* for the secondary socket (FTP), use the "connect to host"
* but ignore the "connect to port" (use the secondary port)
*/
- result = CONNECT(cf, data, ts);
+ result = H2_CONNECT(cf, data, ts);
out:
- *done = (result == CURLE_OK) && (ts->state == TUNNEL_ESTABLISHED);
+ *done = (result == CURLE_OK) && (ts->state == H2_TUNNEL_ESTABLISHED);
cf->connected = *done;
CF_DATA_RESTORE(cf, save);
return result;
@@ -1082,7 +1108,7 @@ static bool cf_h2_proxy_data_pending(struct Curl_cfilter *cf,
{
struct cf_h2_proxy_ctx *ctx = cf->ctx;
if((ctx && !Curl_bufq_is_empty(&ctx->inbufq)) ||
- (ctx && ctx->tunnel.state == TUNNEL_ESTABLISHED &&
+ (ctx && ctx->tunnel.state == H2_TUNNEL_ESTABLISHED &&
!Curl_bufq_is_empty(&ctx->tunnel.recvbuf)))
return TRUE;
return cf->next? cf->next->cft->has_data_pending(cf->next, data) : FALSE;
@@ -1188,14 +1214,14 @@ static ssize_t cf_h2_proxy_recv(struct Curl_cfilter *cf,
struct cf_call_data save;
CURLcode result;
- if(ctx->tunnel.state != TUNNEL_ESTABLISHED) {
+ if(ctx->tunnel.state != H2_TUNNEL_ESTABLISHED) {
*err = CURLE_RECV_ERROR;
return -1;
}
CF_DATA_SAVE(save, cf, data);
if(Curl_bufq_is_empty(&ctx->tunnel.recvbuf)) {
- *err = h2_progress_ingress(cf, data);
+ *err = proxy_h2_progress_ingress(cf, data);
if(*err)
goto out;
}
@@ -1208,13 +1234,19 @@ static ssize_t cf_h2_proxy_recv(struct Curl_cfilter *cf,
nghttp2_session_consume(ctx->h2, ctx->tunnel.stream_id, (size_t)nread);
}
- result = h2_progress_egress(cf, data);
- if(result) {
+ result = proxy_h2_progress_egress(cf, data);
+ if(result && result != CURLE_AGAIN) {
*err = result;
nread = -1;
}
out:
+ if(!Curl_bufq_is_empty(&ctx->tunnel.recvbuf) &&
+ (nread >= 0 || *err == CURLE_AGAIN)) {
+ /* data pending and no fatal error to report. Need to trigger
+ * draining to avoid stalling when no socket events happen. */
+ drain_tunnel(cf, data, &ctx->tunnel);
+ }
DEBUGF(LOG_CF(data, cf, "[h2sid=%u] cf_recv(len=%zu) -> %zd %d",
ctx->tunnel.stream_id, len, nread, *err));
CF_DATA_RESTORE(cf, save);
@@ -1223,93 +1255,188 @@ out:
static ssize_t cf_h2_proxy_send(struct Curl_cfilter *cf,
struct Curl_easy *data,
- const void *mem, size_t len, CURLcode *err)
+ const void *buf, size_t len, CURLcode *err)
{
struct cf_h2_proxy_ctx *ctx = cf->ctx;
struct cf_call_data save;
- ssize_t nwritten = -1;
- const unsigned char *buf = mem;
- size_t start_len = len;
int rv;
+ ssize_t nwritten;
+ CURLcode result;
+ int blocked = 0;
- if(ctx->tunnel.state != TUNNEL_ESTABLISHED) {
+ if(ctx->tunnel.state != H2_TUNNEL_ESTABLISHED) {
*err = CURLE_SEND_ERROR;
return -1;
}
CF_DATA_SAVE(save, cf, data);
- while(len) {
+ if(ctx->tunnel.closed) {
+ nwritten = -1;
+ *err = CURLE_SEND_ERROR;
+ goto out;
+ }
+ else if(ctx->tunnel.upload_blocked_len) {
+ /* the data in `buf` has alread been submitted or added to the
+ * buffers, but have been EAGAINed on the last invocation. */
+ DEBUGASSERT(len >= ctx->tunnel.upload_blocked_len);
+ if(len < ctx->tunnel.upload_blocked_len) {
+ /* Did we get called again with a smaller `len`? This should not
+ * happend. We are not prepared to handle that. */
+ failf(data, "HTTP/2 proxy, send again with decreased length");
+ *err = CURLE_HTTP2;
+ nwritten = -1;
+ goto out;
+ }
+ nwritten = (ssize_t)ctx->tunnel.upload_blocked_len;
+ ctx->tunnel.upload_blocked_len = 0;
+ }
+ else {
nwritten = Curl_bufq_write(&ctx->tunnel.sendbuf, buf, len, err);
- if(nwritten <= 0) {
- if(*err && *err != CURLE_AGAIN) {
- DEBUGF(LOG_CF(data, cf, "error adding data to tunnel sendbuf: %d",
- *err));
- nwritten = -1;
+ if(nwritten < 0) {
+ if(*err != CURLE_AGAIN)
goto out;
- }
- /* blocked */
nwritten = 0;
}
- else {
- DEBUGASSERT((size_t)nwritten <= len);
- buf += (size_t)nwritten;
- len -= (size_t)nwritten;
- }
+ }
- /* resume the tunnel stream and let the h2 session send, which
- * triggers reading from tunnel.sendbuf */
+ if(!Curl_bufq_is_empty(&ctx->tunnel.sendbuf)) {
+ /* req body data is buffered, resume the potentially suspended stream */
rv = nghttp2_session_resume_data(ctx->h2, ctx->tunnel.stream_id);
if(nghttp2_is_fatal(rv)) {
*err = CURLE_SEND_ERROR;
nwritten = -1;
goto out;
}
- *err = h2_progress_egress(cf, data);
- if(*err) {
- nwritten = -1;
- goto out;
- }
-
- if(!nwritten && Curl_bufq_is_full(&ctx->tunnel.sendbuf)) {
- size_t rwin;
- /* we could not add to the buffer and after session processing,
- * it is still full. */
- rwin = nghttp2_session_get_stream_remote_window_size(
- ctx->h2, ctx->tunnel.stream_id);
- DEBUGF(LOG_CF(data, cf, "cf_send: tunnel win %u/%zu",
- nghttp2_session_get_remote_window_size(ctx->h2), rwin));
- if(rwin == 0) {
- /* We cannot upload more as the stream's remote window size
- * is 0. We need to receive WIN_UPDATEs before we can continue.
- */
- data->req.keepon |= KEEP_SEND_HOLD;
- DEBUGF(LOG_CF(data, cf, "pausing send as remote flow "
- "window is exhausted"));
- }
- break;
- }
}
- nwritten = start_len - len;
- if(nwritten > 0) {
- *err = CURLE_OK;
+ /* Call the nghttp2 send loop and flush to write ALL buffered data,
+ * headers and/or request body completely out to the network */
+ result = proxy_h2_progress_egress(cf, data);
+ if(result == CURLE_AGAIN) {
+ blocked = 1;
}
- else if(ctx->tunnel.closed) {
+ else if(result) {
+ *err = result;
nwritten = -1;
- *err = CURLE_SEND_ERROR;
+ goto out;
}
- else {
- nwritten = -1;
+ else if(!Curl_bufq_is_empty(&ctx->tunnel.sendbuf)) {
+ /* although we wrote everything that nghttp2 wants to send now,
+ * there is data left in our stream send buffer unwritten. This may
+ * be due to the stream's HTTP/2 flow window being exhausted. */
+ blocked = 1;
+ }
+
+ if(blocked) {
+ /* Unable to send all data, due to connection blocked or H2 window
+ * exhaustion. Data is left in our stream buffer, or nghttp2's internal
+ * frame buffer or our network out buffer. */
+ size_t rwin = nghttp2_session_get_stream_remote_window_size(
+ ctx->h2, ctx->tunnel.stream_id);
+ if(rwin == 0) {
+ /* H2 flow window exhaustion.
+ * FIXME: there is no way to HOLD all transfers that use this
+ * proxy connection AND to UNHOLD all of them again when the
+ * window increases.
+ * We *could* iterate over all data on this conn maybe? */
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] remote flow "
+ "window is exhausted", ctx->tunnel.stream_id));
+ }
+
+ /* Whatever the cause, we need to return CURL_EAGAIN for this call.
+ * We have unwritten state that needs us being invoked again and EAGAIN
+ * is the only way to ensure that. */
+ ctx->tunnel.upload_blocked_len = nwritten;
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] cf_send(len=%zu) BLOCK: win %u/%zu "
+ "blocked_len=%zu",
+ ctx->tunnel.stream_id, len,
+ nghttp2_session_get_remote_window_size(ctx->h2), rwin,
+ nwritten));
*err = CURLE_AGAIN;
+ nwritten = -1;
+ goto out;
+ }
+ else if(should_close_session(ctx)) {
+ /* nghttp2 thinks this session is done. If the stream has not been
+ * closed, this is an error state for out transfer */
+ if(ctx->tunnel.closed) {
+ *err = CURLE_SEND_ERROR;
+ nwritten = -1;
+ }
+ else {
+ DEBUGF(LOG_CF(data, cf, "send: nothing to do in this session"));
+ *err = CURLE_HTTP2;
+ nwritten = -1;
+ }
}
out:
- DEBUGF(LOG_CF(data, cf, "cf_send(len=%zu) -> %zd, %d ",
- start_len, nwritten, *err));
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] cf_send(len=%zu) -> %zd, %d, "
+ "h2 windows %d-%d (stream-conn), "
+ "buffers %zu-%zu (stream-conn)",
+ ctx->tunnel.stream_id, len, nwritten, *err,
+ nghttp2_session_get_stream_remote_window_size(
+ ctx->h2, ctx->tunnel.stream_id),
+ nghttp2_session_get_remote_window_size(ctx->h2),
+ Curl_bufq_len(&ctx->tunnel.sendbuf),
+ Curl_bufq_len(&ctx->outbufq)));
CF_DATA_RESTORE(cf, save);
return nwritten;
}
+static bool proxy_h2_connisalive(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool *input_pending)
+{
+ struct cf_h2_proxy_ctx *ctx = cf->ctx;
+ bool alive = TRUE;
+
+ *input_pending = FALSE;
+ if(!cf->next || !cf->next->cft->is_alive(cf->next, data, input_pending))
+ return FALSE;
+
+ if(*input_pending) {
+ /* This happens before we've sent off a request and the connection is
+ not in use by any other transfer, there shouldn't be any data here,
+ only "protocol frames" */
+ CURLcode result;
+ ssize_t nread = -1;
+
+ *input_pending = FALSE;
+ nread = Curl_bufq_slurp(&ctx->inbufq, proxy_nw_in_reader, cf, &result);
+ if(nread != -1) {
+ if(proxy_h2_process_pending_input(cf, data, &result) < 0)
+ /* immediate error, considered dead */
+ alive = FALSE;
+ else {
+ alive = !should_close_session(ctx);
+ }
+ }
+ else if(result != CURLE_AGAIN) {
+ /* the read failed so let's say this is dead anyway */
+ alive = FALSE;
+ }
+ }
+
+ return alive;
+}
+
+static bool cf_h2_proxy_is_alive(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool *input_pending)
+{
+ struct cf_h2_proxy_ctx *ctx = cf->ctx;
+ CURLcode result;
+ struct cf_call_data save;
+
+ CF_DATA_SAVE(save, cf, data);
+ result = (ctx && ctx->h2 && proxy_h2_connisalive(cf, data, input_pending));
+ DEBUGF(LOG_CF(data, cf, "conn alive -> %d, input_pending=%d",
+ result, *input_pending));
+ CF_DATA_RESTORE(cf, save);
+ return result;
+}
+
struct Curl_cftype Curl_cft_h2_proxy = {
"H2-PROXY",
CF_TYPE_IP_CONNECT,
@@ -1323,7 +1450,7 @@ struct Curl_cftype Curl_cft_h2_proxy = {
cf_h2_proxy_send,
cf_h2_proxy_recv,
Curl_cf_def_cntrl,
- Curl_cf_def_conn_is_alive,
+ cf_h2_proxy_is_alive,
Curl_cf_def_conn_keep_alive,
Curl_cf_def_query,
};
diff --git a/Utilities/cmcurl/lib/cf-haproxy.c b/Utilities/cmcurl/lib/cf-haproxy.c
index 86d7fd1..ec0100c 100644
--- a/Utilities/cmcurl/lib/cf-haproxy.c
+++ b/Utilities/cmcurl/lib/cf-haproxy.c
@@ -71,6 +71,7 @@ static CURLcode cf_haproxy_date_out_set(struct Curl_cfilter*cf,
struct cf_haproxy_ctx *ctx = cf->ctx;
CURLcode result;
const char *tcp_version;
+ const char *client_ip;
DEBUGASSERT(ctx);
DEBUGASSERT(ctx->state == HAPROXY_INIT);
@@ -82,11 +83,15 @@ static CURLcode cf_haproxy_date_out_set(struct Curl_cfilter*cf,
#endif /* USE_UNIX_SOCKETS */
/* Emit the correct prefix for IPv6 */
tcp_version = cf->conn->bits.ipv6 ? "TCP6" : "TCP4";
+ if(data->set.str[STRING_HAPROXY_CLIENT_IP])
+ client_ip = data->set.str[STRING_HAPROXY_CLIENT_IP];
+ else
+ client_ip = data->info.conn_primary_ip;
result = Curl_dyn_addf(&ctx->data_out, "PROXY %s %s %s %i %i\r\n",
tcp_version,
data->info.conn_local_ip,
- data->info.conn_primary_ip,
+ client_ip,
data->info.conn_local_port,
data->info.conn_primary_port);
@@ -110,7 +115,7 @@ static CURLcode cf_haproxy_connect(struct Curl_cfilter *cf,
return CURLE_OK;
}
- result = cf->next->cft->connect(cf->next, data, blocking, done);
+ result = cf->next->cft->do_connect(cf->next, data, blocking, done);
if(result || !*done)
return result;
@@ -163,7 +168,7 @@ static void cf_haproxy_close(struct Curl_cfilter *cf,
cf->connected = FALSE;
cf_haproxy_ctx_reset(cf->ctx);
if(cf->next)
- cf->next->cft->close(cf->next, data);
+ cf->next->cft->do_close(cf->next, data);
}
static int cf_haproxy_get_select_socks(struct Curl_cfilter *cf,
diff --git a/Utilities/cmcurl/lib/cf-https-connect.c b/Utilities/cmcurl/lib/cf-https-connect.c
index d03cd1e..4e4d4b1 100644
--- a/Utilities/cmcurl/lib/cf-https-connect.c
+++ b/Utilities/cmcurl/lib/cf-https-connect.c
@@ -376,9 +376,9 @@ static bool cf_hc_data_pending(struct Curl_cfilter *cf,
|| cf_hc_baller_data_pending(&ctx->h21_baller, data);
}
-static struct curltime get_max_baller_time(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- int query)
+static struct curltime cf_get_max_baller_time(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ int query)
{
struct cf_hc_ctx *ctx = cf->ctx;
struct Curl_cfilter *cfb;
@@ -408,12 +408,12 @@ static CURLcode cf_hc_query(struct Curl_cfilter *cf,
switch(query) {
case CF_QUERY_TIMER_CONNECT: {
struct curltime *when = pres2;
- *when = get_max_baller_time(cf, data, CF_QUERY_TIMER_CONNECT);
+ *when = cf_get_max_baller_time(cf, data, CF_QUERY_TIMER_CONNECT);
return CURLE_OK;
}
case CF_QUERY_TIMER_APPCONNECT: {
struct curltime *when = pres2;
- *when = get_max_baller_time(cf, data, CF_QUERY_TIMER_APPCONNECT);
+ *when = cf_get_max_baller_time(cf, data, CF_QUERY_TIMER_APPCONNECT);
return CURLE_OK;
}
default:
@@ -432,7 +432,7 @@ static void cf_hc_close(struct Curl_cfilter *cf, struct Curl_easy *data)
cf->connected = FALSE;
if(cf->next) {
- cf->next->cft->close(cf->next, data);
+ cf->next->cft->do_close(cf->next, data);
Curl_conn_cf_discard_chain(&cf->next, data);
}
}
diff --git a/Utilities/cmcurl/lib/cf-socket.c b/Utilities/cmcurl/lib/cf-socket.c
index 960979b..5729fe0 100644
--- a/Utilities/cmcurl/lib/cf-socket.c
+++ b/Utilities/cmcurl/lib/cf-socket.c
@@ -871,7 +871,7 @@ static void cf_socket_close(struct Curl_cfilter *cf, struct Curl_easy *data)
/* this is our local socket, we did never publish it */
DEBUGF(LOG_CF(data, cf, "cf_socket_close(%" CURL_FORMAT_SOCKET_T
", not active)", ctx->sock));
- sclose(ctx->sock);
+ socket_close(data, cf->conn, !ctx->accepted, ctx->sock);
ctx->sock = CURL_SOCKET_BAD;
}
Curl_bufq_reset(&ctx->recvbuf);
@@ -901,22 +901,26 @@ static CURLcode set_local_ip(struct Curl_cfilter *cf,
struct cf_socket_ctx *ctx = cf->ctx;
#ifdef HAVE_GETSOCKNAME
- char buffer[STRERROR_LEN];
- struct Curl_sockaddr_storage ssloc;
- curl_socklen_t slen = sizeof(struct Curl_sockaddr_storage);
+ if(!(data->conn->handler->protocol & CURLPROTO_TFTP)) {
+ /* TFTP does not connect, so it cannot get the IP like this */
- memset(&ssloc, 0, sizeof(ssloc));
- if(getsockname(ctx->sock, (struct sockaddr*) &ssloc, &slen)) {
- int error = SOCKERRNO;
- failf(data, "getsockname() failed with errno %d: %s",
- error, Curl_strerror(error, buffer, sizeof(buffer)));
- return CURLE_FAILED_INIT;
- }
- if(!Curl_addr2string((struct sockaddr*)&ssloc, slen,
- ctx->l_ip, &ctx->l_port)) {
- failf(data, "ssloc inet_ntop() failed with errno %d: %s",
- errno, Curl_strerror(errno, buffer, sizeof(buffer)));
- return CURLE_FAILED_INIT;
+ char buffer[STRERROR_LEN];
+ struct Curl_sockaddr_storage ssloc;
+ curl_socklen_t slen = sizeof(struct Curl_sockaddr_storage);
+
+ memset(&ssloc, 0, sizeof(ssloc));
+ if(getsockname(ctx->sock, (struct sockaddr*) &ssloc, &slen)) {
+ int error = SOCKERRNO;
+ failf(data, "getsockname() failed with errno %d: %s",
+ error, Curl_strerror(error, buffer, sizeof(buffer)));
+ return CURLE_FAILED_INIT;
+ }
+ if(!Curl_addr2string((struct sockaddr*)&ssloc, slen,
+ ctx->l_ip, &ctx->l_port)) {
+ failf(data, "ssloc inet_ntop() failed with errno %d: %s",
+ errno, Curl_strerror(errno, buffer, sizeof(buffer)));
+ return CURLE_FAILED_INIT;
+ }
}
#else
(void)data;
@@ -1356,26 +1360,31 @@ out:
static void conn_set_primary_ip(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
- struct cf_socket_ctx *ctx = cf->ctx;
#ifdef HAVE_GETPEERNAME
- char buffer[STRERROR_LEN];
- struct Curl_sockaddr_storage ssrem;
- curl_socklen_t plen;
- int port;
+ struct cf_socket_ctx *ctx = cf->ctx;
+ if(!(data->conn->handler->protocol & CURLPROTO_TFTP)) {
+ /* TFTP does not connect the endpoint: getpeername() failed with errno
+ 107: Transport endpoint is not connected */
- plen = sizeof(ssrem);
- memset(&ssrem, 0, plen);
- if(getpeername(ctx->sock, (struct sockaddr*) &ssrem, &plen)) {
- int error = SOCKERRNO;
- failf(data, "getpeername() failed with errno %d: %s",
- error, Curl_strerror(error, buffer, sizeof(buffer)));
- return;
- }
- if(!Curl_addr2string((struct sockaddr*)&ssrem, plen,
- cf->conn->primary_ip, &port)) {
- failf(data, "ssrem inet_ntop() failed with errno %d: %s",
- errno, Curl_strerror(errno, buffer, sizeof(buffer)));
- return;
+ char buffer[STRERROR_LEN];
+ struct Curl_sockaddr_storage ssrem;
+ curl_socklen_t plen;
+ int port;
+
+ plen = sizeof(ssrem);
+ memset(&ssrem, 0, plen);
+ if(getpeername(ctx->sock, (struct sockaddr*) &ssrem, &plen)) {
+ int error = SOCKERRNO;
+ failf(data, "getpeername() failed with errno %d: %s",
+ error, Curl_strerror(error, buffer, sizeof(buffer)));
+ return;
+ }
+ if(!Curl_addr2string((struct sockaddr*)&ssrem, plen,
+ cf->conn->primary_ip, &port)) {
+ failf(data, "ssrem inet_ntop() failed with errno %d: %s",
+ errno, Curl_strerror(errno, buffer, sizeof(buffer)));
+ return;
+ }
}
#else
cf->conn->primary_ip[0] = 0;
diff --git a/Utilities/cmcurl/lib/cfilters.c b/Utilities/cmcurl/lib/cfilters.c
index 291c823..216d0b4 100644
--- a/Utilities/cmcurl/lib/cfilters.c
+++ b/Utilities/cmcurl/lib/cfilters.c
@@ -50,7 +50,7 @@ void Curl_cf_def_close(struct Curl_cfilter *cf, struct Curl_easy *data)
{
cf->connected = FALSE;
if(cf->next)
- cf->next->cft->close(cf->next, data);
+ cf->next->cft->do_close(cf->next, data);
}
#endif
@@ -161,7 +161,7 @@ void Curl_conn_close(struct Curl_easy *data, int index)
/* it is valid to call that without filters being present */
cf = data->conn->cfilter[index];
if(cf) {
- cf->cft->close(cf, data);
+ cf->cft->do_close(cf, data);
}
}
@@ -179,7 +179,7 @@ ssize_t Curl_conn_recv(struct Curl_easy *data, int num, char *buf,
if(cf) {
return cf->cft->do_recv(cf, data, buf, len, code);
}
- failf(data, CMSGI(data->conn, num, "recv: no filter connected"));
+ failf(data, "recv: no filter connected");
*code = CURLE_FAILED_INIT;
return -1;
}
@@ -198,7 +198,7 @@ ssize_t Curl_conn_send(struct Curl_easy *data, int num,
if(cf) {
return cf->cft->do_send(cf, data, mem, len, code);
}
- failf(data, CMSGI(data->conn, num, "send: no filter connected"));
+ failf(data, "send: no filter connected");
DEBUGASSERT(0);
*code = CURLE_FAILED_INIT;
return -1;
@@ -293,14 +293,14 @@ CURLcode Curl_conn_cf_connect(struct Curl_cfilter *cf,
bool blocking, bool *done)
{
if(cf)
- return cf->cft->connect(cf, data, blocking, done);
+ return cf->cft->do_connect(cf, data, blocking, done);
return CURLE_FAILED_INIT;
}
void Curl_conn_cf_close(struct Curl_cfilter *cf, struct Curl_easy *data)
{
if(cf)
- cf->cft->close(cf, data);
+ cf->cft->do_close(cf, data);
}
int Curl_conn_cf_get_select_socks(struct Curl_cfilter *cf,
@@ -348,7 +348,7 @@ CURLcode Curl_conn_connect(struct Curl_easy *data,
*done = cf->connected;
if(!*done) {
- result = cf->cft->connect(cf, data, blocking, done);
+ result = cf->cft->do_connect(cf, data, blocking, done);
if(!result && *done) {
Curl_conn_ev_update_info(data, data->conn);
conn_report_connect_stats(data, data->conn);
diff --git a/Utilities/cmcurl/lib/cfilters.h b/Utilities/cmcurl/lib/cfilters.h
index 70dcbe7..2c65264 100644
--- a/Utilities/cmcurl/lib/cfilters.h
+++ b/Utilities/cmcurl/lib/cfilters.h
@@ -168,8 +168,8 @@ struct Curl_cftype {
int flags; /* flags of filter type */
int log_level; /* log level for such filters */
Curl_cft_destroy_this *destroy; /* destroy resources of this cf */
- Curl_cft_connect *connect; /* establish connection */
- Curl_cft_close *close; /* close conn */
+ Curl_cft_connect *do_connect; /* establish connection */
+ Curl_cft_close *do_close; /* close conn */
Curl_cft_get_host *get_host; /* host filter talks to */
Curl_cft_get_select_socks *get_select_socks;/* sockets to select on */
Curl_cft_data_pending *has_data_pending;/* conn has data pending */
diff --git a/Utilities/cmcurl/lib/conncache.h b/Utilities/cmcurl/lib/conncache.h
index 959767d..c60f844 100644
--- a/Utilities/cmcurl/lib/conncache.h
+++ b/Utilities/cmcurl/lib/conncache.h
@@ -39,7 +39,8 @@ struct connectdata;
struct conncache {
struct Curl_hash hash;
size_t num_conn;
- long next_connection_id;
+ curl_off_t next_connection_id;
+ curl_off_t next_easy_id;
struct curltime last_cleanup;
/* handle used for closing cached connections */
struct Curl_easy *closure_handle;
diff --git a/Utilities/cmcurl/lib/connect.c b/Utilities/cmcurl/lib/connect.c
index ed55121..dc93533 100644
--- a/Utilities/cmcurl/lib/connect.c
+++ b/Utilities/cmcurl/lib/connect.c
@@ -253,7 +253,7 @@ bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen,
}
struct connfind {
- long id_tofind;
+ curl_off_t id_tofind;
struct connectdata *found;
};
@@ -937,7 +937,7 @@ static void cf_he_close(struct Curl_cfilter *cf,
ctx->state = SCFST_INIT;
if(cf->next) {
- cf->next->cft->close(cf->next, data);
+ cf->next->cft->do_close(cf->next, data);
Curl_conn_cf_discard_chain(&cf->next, data);
}
}
@@ -1291,7 +1291,7 @@ static void cf_setup_close(struct Curl_cfilter *cf,
ctx->state = CF_SETUP_INIT;
if(cf->next) {
- cf->next->cft->close(cf->next, data);
+ cf->next->cft->do_close(cf->next, data);
Curl_conn_cf_discard_chain(&cf->next, data);
}
}
diff --git a/Utilities/cmcurl/lib/cookie.c b/Utilities/cmcurl/lib/cookie.c
index 0303efb..4345a84 100644
--- a/Utilities/cmcurl/lib/cookie.c
+++ b/Utilities/cmcurl/lib/cookie.c
@@ -123,8 +123,9 @@ static void freecookie(struct Cookie *co)
free(co);
}
-static bool tailmatch(const char *cookie_domain, size_t cookie_domain_len,
- const char *hostname)
+static bool cookie_tailmatch(const char *cookie_domain,
+ size_t cookie_domain_len,
+ const char *hostname)
{
size_t hostname_len = strlen(hostname);
@@ -696,7 +697,7 @@ Curl_cookie_add(struct Curl_easy *data,
if(!domain
|| (is_ip && !strncmp(valuep, domain, vlen) &&
(vlen == strlen(domain)))
- || (!is_ip && tailmatch(valuep, vlen, domain))) {
+ || (!is_ip && cookie_tailmatch(valuep, vlen, domain))) {
strstore(&co->domain, valuep, vlen);
if(!co->domain) {
badcookie = TRUE;
@@ -1431,7 +1432,7 @@ struct Cookie *Curl_cookie_getlist(struct Curl_easy *data,
/* now check if the domain is correct */
if(!co->domain ||
(co->tailmatch && !is_ip &&
- tailmatch(co->domain, strlen(co->domain), host)) ||
+ cookie_tailmatch(co->domain, strlen(co->domain), host)) ||
((!co->tailmatch || is_ip) && strcasecompare(host, co->domain)) ) {
/*
* the right part of the host matches the domain stuff in the
diff --git a/Utilities/cmcurl/lib/curl_config.h.cmake b/Utilities/cmcurl/lib/curl_config.h.cmake
index 6e2458d..4ab8242 100644
--- a/Utilities/cmcurl/lib/curl_config.h.cmake
+++ b/Utilities/cmcurl/lib/curl_config.h.cmake
@@ -443,6 +443,9 @@
/* Define to 1 if you have the sigsetjmp function or macro. */
#cmakedefine HAVE_SIGSETJMP 1
+/* Define to 1 if you have the `snprintf' function. */
+#cmakedefine HAVE_SNPRINTF
+
/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */
#cmakedefine HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1
@@ -572,9 +575,6 @@
/* Define to 1 if you have the windows.h header file. */
#cmakedefine HAVE_WINDOWS_H 1
-/* Define to 1 if you have the winldap.h header file. */
-#cmakedefine HAVE_WINLDAP_H 1
-
/* Define to 1 if you have the winsock2.h header file. */
#cmakedefine HAVE_WINSOCK2_H 1
diff --git a/Utilities/cmcurl/lib/curl_log.c b/Utilities/cmcurl/lib/curl_log.c
index 71024cf..782c35a 100644
--- a/Utilities/cmcurl/lib/curl_log.c
+++ b/Utilities/cmcurl/lib/curl_log.c
@@ -130,13 +130,11 @@ void Curl_log_cf_debug(struct Curl_easy *data, struct Curl_cfilter *cf,
const char *fmt, ...)
{
DEBUGASSERT(cf);
- if(data && Curl_log_cf_is_debug(cf)) {
+ if(data && Curl_log_cf_is_debug(cf, data)) {
va_list ap;
int len;
char buffer[MAXINFO + 2];
- len = msnprintf(buffer, MAXINFO, "[CONN-%ld%s-%s] ",
- cf->conn->connection_id, cf->sockindex? "/2" : "",
- cf->cft->name);
+ len = msnprintf(buffer, MAXINFO, "[%s] ", cf->cft->name);
va_start(ap, fmt);
len += mvsnprintf(buffer + len, MAXINFO - len, fmt, ap);
va_end(ap);
diff --git a/Utilities/cmcurl/lib/curl_log.h b/Utilities/cmcurl/lib/curl_log.h
index ad6143f..ebfa5a0 100644
--- a/Utilities/cmcurl/lib/curl_log.h
+++ b/Utilities/cmcurl/lib/curl_log.h
@@ -74,7 +74,7 @@ void Curl_debug(struct Curl_easy *data, curl_infotype type,
defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
#define LOG_CF(data, cf, ...) \
- do { if(Curl_log_cf_is_debug(cf)) \
+ do { if(Curl_log_cf_is_debug(cf, data)) \
Curl_log_cf_debug(data, cf, __VA_ARGS__); } while(0)
#else
#define LOG_CF Curl_log_cf_debug
@@ -90,8 +90,10 @@ void Curl_log_cf_debug(struct Curl_easy *data, struct Curl_cfilter *cf,
const char *fmt, ...);
#endif
-#define Curl_log_cf_is_debug(cf) \
- ((cf) && (cf)->cft->log_level >= CURL_LOG_DEBUG)
+#define Curl_log_cf_is_debug(cf, data) \
+ ((data) && (data)->set.verbose && \
+ (cf) && (cf)->cft->log_level >= CURL_LOG_DEBUG)
+
#else /* !DEBUGBUILD */
@@ -110,29 +112,10 @@ void Curl_log_cf_debug(struct Curl_easy *data, struct Curl_cfilter *cf,
const char *fmt, ...);
#endif
-#define Curl_log_cf_is_debug(x) ((void)(x), FALSE)
+#define Curl_log_cf_is_debug(x,y) ((void)(x), (void)(y), FALSE)
#endif /* !DEBUGBUILD */
-#define LOG_CF_IS_DEBUG(x) Curl_log_cf_is_debug(x)
-
-/* Macros intended for DEBUGF logging, use like:
- * DEBUGF(infof(data, CFMSG(cf, "this filter %s rocks"), "very much"));
- * and it will output:
- * [CONN-1-0][CF-SSL] this filter very much rocks
- * on connection #1 with sockindex 0 for filter of type "SSL". */
-#define DMSG(d,msg) \
- "[CONN-%ld] "msg, (d)->conn->connection_id
-#define DMSGI(d,i,msg) \
- "[CONN-%ld-%d] "msg, (d)->conn->connection_id, (i)
-#define CMSG(c,msg) \
- "[CONN-%ld] "msg, (c)->connection_id
-#define CMSGI(c,i,msg) \
- "[CONN-%ld-%d] "msg, (c)->connection_id, (i)
-#define CFMSG(cf,msg) \
- "[CONN-%ld-%d][CF-%s] "msg, (cf)->conn->connection_id, \
- (cf)->sockindex, (cf)->cft->name
-
-
+#define LOG_CF_IS_DEBUG(cf, data) Curl_log_cf_is_debug(cf, data)
#endif /* HEADER_CURL_LOG_H */
diff --git a/Utilities/cmcurl/lib/curl_memory.h b/Utilities/cmcurl/lib/curl_memory.h
index 1a21c5a..b8c46d7 100644
--- a/Utilities/cmcurl/lib/curl_memory.h
+++ b/Utilities/cmcurl/lib/curl_memory.h
@@ -55,9 +55,65 @@
*/
#ifdef HEADER_CURL_MEMDEBUG_H
-#error "Header memdebug.h shall not be included before curl_memory.h"
+/* cleanup after memdebug.h */
+
+#ifdef MEMDEBUG_NODEFINES
+#ifdef CURLDEBUG
+
+#undef strdup
+#undef malloc
+#undef calloc
+#undef realloc
+#undef free
+#undef send
+#undef recv
+
+#ifdef WIN32
+# ifdef UNICODE
+# undef wcsdup
+# undef _wcsdup
+# undef _tcsdup
+# else
+# undef _tcsdup
+# endif
+#endif
+
+#undef socket
+#undef accept
+#ifdef HAVE_SOCKETPAIR
+#undef socketpair
#endif
+#ifdef HAVE_GETADDRINFO
+#if defined(getaddrinfo) && defined(__osf__)
+#undef ogetaddrinfo
+#else
+#undef getaddrinfo
+#endif
+#endif /* HAVE_GETADDRINFO */
+
+#ifdef HAVE_FREEADDRINFO
+#undef freeaddrinfo
+#endif /* HAVE_FREEADDRINFO */
+
+/* sclose is probably already defined, redefine it! */
+#undef sclose
+#undef fopen
+#undef fdopen
+#undef fclose
+
+#endif /* MEMDEBUG_NODEFINES */
+#endif /* CURLDEBUG */
+
+#undef HEADER_CURL_MEMDEBUG_H
+#endif /* HEADER_CURL_MEMDEBUG_H */
+
+/*
+** Following section applies even when CURLDEBUG is not defined.
+*/
+
+#undef fake_sclose
+
#ifndef CURL_DID_MEMORY_FUNC_TYPEDEFS /* only if not already done */
/*
* The following memory function replacement typedef's are COPIED from
diff --git a/Utilities/cmcurl/lib/curl_printf.h b/Utilities/cmcurl/lib/curl_printf.h
index 6d3d492..46ef344 100644
--- a/Utilities/cmcurl/lib/curl_printf.h
+++ b/Utilities/cmcurl/lib/curl_printf.h
@@ -37,6 +37,7 @@
# undef vprintf
# undef vfprintf
# undef vsnprintf
+# undef mvsnprintf
# undef aprintf
# undef vaprintf
# define printf curl_mprintf
diff --git a/Utilities/cmcurl/lib/curl_sasl.c b/Utilities/cmcurl/lib/curl_sasl.c
index 119fb9b..1cb0e54 100644
--- a/Utilities/cmcurl/lib/curl_sasl.c
+++ b/Utilities/cmcurl/lib/curl_sasl.c
@@ -221,12 +221,12 @@ void Curl_sasl_init(struct SASL *sasl, struct Curl_easy *data,
}
/*
- * state()
+ * sasl_state()
*
* This is the ONLY way to change SASL state!
*/
-static void state(struct SASL *sasl, struct Curl_easy *data,
- saslstate newstate)
+static void sasl_state(struct SASL *sasl, struct Curl_easy *data,
+ saslstate newstate)
{
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* for debug purposes */
@@ -508,7 +508,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
if(!result) {
*progress = SASL_INPROGRESS;
- state(sasl, data, Curl_bufref_ptr(&resp) ? state2 : state1);
+ sasl_state(sasl, data, Curl_bufref_ptr(&resp) ? state2 : state1);
}
}
@@ -548,14 +548,14 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
if(code != sasl->params->finalcode)
result = CURLE_LOGIN_DENIED;
*progress = SASL_DONE;
- state(sasl, data, SASL_STOP);
+ sasl_state(sasl, data, SASL_STOP);
return result;
}
if(sasl->state != SASL_CANCEL && sasl->state != SASL_OAUTH2_RESP &&
code != sasl->params->contcode) {
*progress = SASL_DONE;
- state(sasl, data, SASL_STOP);
+ sasl_state(sasl, data, SASL_STOP);
return CURLE_LOGIN_DENIED;
}
@@ -698,7 +698,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
if(code == sasl->params->finalcode) {
/* Final response was received so we are done */
*progress = SASL_DONE;
- state(sasl, data, SASL_STOP);
+ sasl_state(sasl, data, SASL_STOP);
return result;
}
else if(code == sasl->params->contcode) {
@@ -708,7 +708,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
}
else {
*progress = SASL_DONE;
- state(sasl, data, SASL_STOP);
+ sasl_state(sasl, data, SASL_STOP);
return CURLE_LOGIN_DENIED;
}
@@ -745,7 +745,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
Curl_bufref_free(&resp);
- state(sasl, data, newstate);
+ sasl_state(sasl, data, newstate);
return result;
}
diff --git a/Utilities/cmcurl/lib/curl_setup.h b/Utilities/cmcurl/lib/curl_setup.h
index 9043d97..e395be5 100644
--- a/Utilities/cmcurl/lib/curl_setup.h
+++ b/Utilities/cmcurl/lib/curl_setup.h
@@ -262,7 +262,7 @@
#if defined(__APPLE__) && !defined(USE_ARES)
#include <TargetConditionals.h>
#define USE_RESOLVE_ON_IPS 1
-# if defined(TARGET_OS_OSX) && TARGET_OS_OSX
+# if !defined(TARGET_OS_OSX) || TARGET_OS_OSX
# define CURL_OSX_CALL_COPYPROXIES 1
# endif
#endif
@@ -302,6 +302,7 @@
# if defined(HAVE_PROTO_BSDSOCKET_H) && \
(!defined(__amigaos4__) || defined(USE_AMISSL))
/* use bsdsocket.library directly, instead of libc networking functions */
+# define _SYS_MBUF_H /* m_len define clashes with curl */
# include <proto/bsdsocket.h>
# ifdef __amigaos4__
int Curl_amiga_select(int nfds, fd_set *readfds, fd_set *writefds,
diff --git a/Utilities/cmcurl/lib/curl_setup_once.h b/Utilities/cmcurl/lib/curl_setup_once.h
index dde7229..c1ed059 100644
--- a/Utilities/cmcurl/lib/curl_setup_once.h
+++ b/Utilities/cmcurl/lib/curl_setup_once.h
@@ -77,6 +77,12 @@
# endif
#endif
+#ifdef USE_SCHANNEL
+/* Must set this before <schannel.h> is included directly or indirectly by
+ another Windows header. */
+# define SCHANNEL_USE_BLACKLISTS 1
+#endif
+
#ifdef __hpux
# if !defined(_XOPEN_SOURCE_EXTENDED) || defined(_KERNEL)
# ifdef _APP32_64BIT_OFF_T
diff --git a/Utilities/cmcurl/lib/dynbuf.h b/Utilities/cmcurl/lib/dynbuf.h
index 57ad62b..6291eab 100644
--- a/Utilities/cmcurl/lib/dynbuf.h
+++ b/Utilities/cmcurl/lib/dynbuf.h
@@ -81,8 +81,6 @@ int Curl_dyn_vprintf(struct dynbuf *dyn, const char *format, va_list ap_save);
#define DYN_PAUSE_BUFFER (64 * 1024 * 1024)
#define DYN_HAXPROXY 2048
#define DYN_HTTP_REQUEST (1024*1024)
-#define DYN_H2_HEADERS (128*1024)
-#define DYN_H2_TRAILERS (128*1024)
#define DYN_APRINTF 8000000
#define DYN_RTSP_REQ_HEADER (64*1024)
#define DYN_TRAILERS (64*1024)
diff --git a/Utilities/cmcurl/lib/easy.c b/Utilities/cmcurl/lib/easy.c
index d36cc03..d034629 100644
--- a/Utilities/cmcurl/lib/easy.c
+++ b/Utilities/cmcurl/lib/easy.c
@@ -63,6 +63,7 @@
#include "slist.h"
#include "mime.h"
#include "amigaos.h"
+#include "macos.h"
#include "warnless.h"
#include "sigpipe.h"
#include "vssh/ssh.h"
@@ -83,7 +84,7 @@
/* true globals -- for curl_global_init() and curl_global_cleanup() */
static unsigned int initialized;
-static long init_flags;
+static long easy_init_flags;
#ifdef GLOBAL_INIT_IS_THREADSAFE
@@ -181,6 +182,11 @@ static CURLcode global_init(long flags, bool memoryfuncs)
}
#endif
+ if(Curl_macos_init()) {
+ DEBUGF(fprintf(stderr, "Error: Curl_macos_init failed\n"));
+ goto fail;
+ }
+
if(Curl_resolver_global_init()) {
DEBUGF(fprintf(stderr, "Error: resolver_global_init failed\n"));
goto fail;
@@ -199,7 +205,7 @@ static CURLcode global_init(long flags, bool memoryfuncs)
}
#endif
- init_flags = flags;
+ easy_init_flags = flags;
#ifdef DEBUGBUILD
if(getenv("CURL_GLOBAL_INIT"))
@@ -274,7 +280,7 @@ CURLcode curl_global_init_mem(long flags, curl_malloc_callback m,
/**
* curl_global_cleanup() globally cleanups curl, uses the value of
- * "init_flags" to determine what needs to be cleaned up and what doesn't.
+ * "easy_init_flags" to determine what needs to be cleaned up and what doesn't.
*/
void curl_global_cleanup(void)
{
@@ -294,7 +300,7 @@ void curl_global_cleanup(void)
Curl_resolver_global_cleanup();
#ifdef WIN32
- Curl_win32_cleanup(init_flags);
+ Curl_win32_cleanup(easy_init_flags);
#endif
Curl_amiga_cleanup();
@@ -308,7 +314,7 @@ void curl_global_cleanup(void)
free(leakpointer);
#endif
- init_flags = 0;
+ easy_init_flags = 0;
global_init_unlock();
}
@@ -893,6 +899,8 @@ 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_id = -1;
+ outcurl->state.recent_conn_id = -1;
+ outcurl->id = -1;
outcurl->progress.flags = data->progress.flags;
outcurl->progress.callback = data->progress.callback;
diff --git a/Utilities/cmcurl/lib/easy_lock.h b/Utilities/cmcurl/lib/easy_lock.h
index 5fa9477..6399a39 100644
--- a/Utilities/cmcurl/lib/easy_lock.h
+++ b/Utilities/cmcurl/lib/easy_lock.h
@@ -1,3 +1,5 @@
+#ifndef HEADER_CURL_EASY_LOCK_H
+#define HEADER_CURL_EASY_LOCK_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -103,3 +105,5 @@ static inline void curl_simple_lock_unlock(curl_simple_lock *lock)
#undef GLOBAL_INIT_IS_THREADSAFE
#endif
+
+#endif /* HEADER_CURL_EASY_LOCK_H */
diff --git a/Utilities/cmcurl/lib/easyoptions.c b/Utilities/cmcurl/lib/easyoptions.c
index a9c1efd..e69c658 100644
--- a/Utilities/cmcurl/lib/easyoptions.c
+++ b/Utilities/cmcurl/lib/easyoptions.c
@@ -120,6 +120,7 @@ struct curl_easyoption Curl_easyopts[] = {
{"HAPPY_EYEBALLS_TIMEOUT_MS", CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS,
CURLOT_LONG, 0},
{"HAPROXYPROTOCOL", CURLOPT_HAPROXYPROTOCOL, CURLOT_LONG, 0},
+ {"HAPROXY_CLIENT_IP", CURLOPT_HAPROXY_CLIENT_IP, CURLOT_STRING, 0},
{"HEADER", CURLOPT_HEADER, CURLOT_LONG, 0},
{"HEADERDATA", CURLOPT_HEADERDATA, CURLOT_CBPTR, 0},
{"HEADERFUNCTION", CURLOPT_HEADERFUNCTION, CURLOT_FUNCTION, 0},
@@ -164,7 +165,9 @@ struct curl_easyoption Curl_easyopts[] = {
{"MAIL_AUTH", CURLOPT_MAIL_AUTH, CURLOT_STRING, 0},
{"MAIL_FROM", CURLOPT_MAIL_FROM, CURLOT_STRING, 0},
{"MAIL_RCPT", CURLOPT_MAIL_RCPT, CURLOT_SLIST, 0},
- {"MAIL_RCPT_ALLLOWFAILS", CURLOPT_MAIL_RCPT_ALLLOWFAILS, CURLOT_LONG, 0},
+ {"MAIL_RCPT_ALLLOWFAILS", CURLOPT_MAIL_RCPT_ALLOWFAILS,
+ CURLOT_LONG, CURLOT_FLAG_ALIAS},
+ {"MAIL_RCPT_ALLOWFAILS", CURLOPT_MAIL_RCPT_ALLOWFAILS, CURLOT_LONG, 0},
{"MAXAGE_CONN", CURLOPT_MAXAGE_CONN, CURLOT_LONG, 0},
{"MAXCONNECTS", CURLOPT_MAXCONNECTS, CURLOT_LONG, 0},
{"MAXFILESIZE", CURLOPT_MAXFILESIZE, CURLOT_LONG, 0},
@@ -370,6 +373,6 @@ struct curl_easyoption Curl_easyopts[] = {
*/
int Curl_easyopts_check(void)
{
- return ((CURLOPT_LASTENTRY%10000) != (322 + 1));
+ return ((CURLOPT_LASTENTRY%10000) != (323 + 1));
}
#endif
diff --git a/Utilities/cmcurl/lib/fopen.c b/Utilities/cmcurl/lib/fopen.c
index f710dbf..b6e3cad 100644
--- a/Utilities/cmcurl/lib/fopen.c
+++ b/Utilities/cmcurl/lib/fopen.c
@@ -56,13 +56,13 @@ CURLcode Curl_fopen(struct Curl_easy *data, const char *filename,
int fd = -1;
*tempname = NULL;
- if(stat(filename, &sb) == -1 || !S_ISREG(sb.st_mode)) {
- /* a non-regular file, fallback to direct fopen() */
- *fh = fopen(filename, FOPEN_WRITETEXT);
- if(*fh)
- return CURLE_OK;
+ *fh = fopen(filename, FOPEN_WRITETEXT);
+ if(!*fh)
goto fail;
- }
+ if(fstat(fileno(*fh), &sb) == -1 || !S_ISREG(sb.st_mode))
+ return CURLE_OK;
+ fclose(*fh);
+ *fh = NULL;
result = Curl_rand_hex(data, randsuffix, sizeof(randsuffix));
if(result)
@@ -85,7 +85,7 @@ CURLcode Curl_fopen(struct Curl_easy *data, const char *filename,
if((fstat(fd, &nsb) != -1) &&
(nsb.st_uid == sb.st_uid) && (nsb.st_gid == sb.st_gid)) {
/* if the user and group are the same, clone the original mode */
- if(fchmod(fd, sb.st_mode) == -1)
+ if(fchmod(fd, (mode_t)sb.st_mode) == -1)
goto fail;
}
}
diff --git a/Utilities/cmcurl/lib/ftp.c b/Utilities/cmcurl/lib/ftp.c
index 4f50cb4..a1cfa65 100644
--- a/Utilities/cmcurl/lib/ftp.c
+++ b/Utilities/cmcurl/lib/ftp.c
@@ -93,14 +93,14 @@
/* Local API functions */
#ifndef DEBUGBUILD
-static void _state(struct Curl_easy *data,
- ftpstate newstate);
-#define state(x,y) _state(x,y)
+static void _ftp_state(struct Curl_easy *data,
+ ftpstate newstate);
+#define ftp_state(x,y) _ftp_state(x,y)
#else
-static void _state(struct Curl_easy *data,
- ftpstate newstate,
- int lineno);
-#define state(x,y) _state(x,y,__LINE__)
+static void _ftp_state(struct Curl_easy *data,
+ ftpstate newstate,
+ int lineno);
+#define ftp_state(x,y) _ftp_state(x,y,__LINE__)
#endif
static CURLcode ftp_sendquote(struct Curl_easy *data,
@@ -463,7 +463,7 @@ static CURLcode InitiateTransfer(struct Curl_easy *data)
}
conn->proto.ftpc.pp.pending_resp = TRUE; /* expect server response */
- state(data, FTP_STOP);
+ ftp_state(data, FTP_STOP);
return CURLE_OK;
}
@@ -591,7 +591,7 @@ static CURLcode ftp_readresp(struct Curl_easy *data,
* generically is a good idea.
*/
infof(data, "We got a 421 - timeout");
- state(data, FTP_STOP);
+ ftp_state(data, FTP_STOP);
return CURLE_OPERATION_TIMEDOUT;
}
@@ -750,10 +750,10 @@ static const char * const ftp_state_names[]={
#endif
/* This is the ONLY way to change FTP state! */
-static void _state(struct Curl_easy *data,
- ftpstate newstate
+static void _ftp_state(struct Curl_easy *data,
+ ftpstate newstate
#ifdef DEBUGBUILD
- , int lineno
+ , int lineno
#endif
)
{
@@ -784,7 +784,7 @@ static CURLcode ftp_state_user(struct Curl_easy *data,
if(!result) {
struct ftp_conn *ftpc = &conn->proto.ftpc;
ftpc->ftp_trying_alternative = FALSE;
- state(data, FTP_USER);
+ ftp_state(data, FTP_USER);
}
return result;
}
@@ -794,7 +794,7 @@ static CURLcode ftp_state_pwd(struct Curl_easy *data,
{
CURLcode result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "%s", "PWD");
if(!result)
- state(data, FTP_PWD);
+ ftp_state(data, FTP_PWD);
return result;
}
@@ -872,7 +872,7 @@ static CURLcode ftp_state_cwd(struct Curl_easy *data,
for all upcoming ones in the ftp->dirs[] array */
result = Curl_pp_sendf(data, &ftpc->pp, "CWD %s", ftpc->entrypath);
if(!result)
- state(data, FTP_CWD);
+ ftp_state(data, FTP_CWD);
}
else {
if(ftpc->dirdepth) {
@@ -882,7 +882,7 @@ static CURLcode ftp_state_cwd(struct Curl_easy *data,
result = Curl_pp_sendf(data, &ftpc->pp, "CWD %s",
ftpc->dirs[ftpc->cwdcount -1]);
if(!result)
- state(data, FTP_CWD);
+ ftp_state(data, FTP_CWD);
}
else {
/* No CWD necessary */
@@ -1261,11 +1261,11 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
if(result)
goto out;
portsock = CURL_SOCKET_BAD; /* now held in filter */
- state(data, FTP_PORT);
+ ftp_state(data, FTP_PORT);
out:
if(result) {
- state(data, FTP_STOP);
+ ftp_state(data, FTP_STOP);
}
if(portsock != CURL_SOCKET_BAD)
Curl_socket_close(data, conn, portsock);
@@ -1307,7 +1307,7 @@ static CURLcode ftp_state_use_pasv(struct Curl_easy *data,
result = Curl_pp_sendf(data, &ftpc->pp, "%s", mode[modeoff]);
if(!result) {
ftpc->count1 = modeoff;
- state(data, FTP_PASV);
+ ftp_state(data, FTP_PASV);
infof(data, "Connect data stream passively");
}
return result;
@@ -1330,7 +1330,7 @@ static CURLcode ftp_state_prepare_transfer(struct Curl_easy *data)
/* doesn't transfer any data */
/* still possibly do PRE QUOTE jobs */
- state(data, FTP_RETR_PREQUOTE);
+ ftp_state(data, FTP_RETR_PREQUOTE);
result = ftp_state_quote(data, TRUE, FTP_RETR_PREQUOTE);
}
else if(data->set.ftp_use_port) {
@@ -1355,7 +1355,7 @@ static CURLcode ftp_state_prepare_transfer(struct Curl_easy *data)
result = Curl_pp_sendf(data, &ftpc->pp, "PRET RETR %s",
conn->proto.ftpc.file);
if(!result)
- state(data, FTP_PRET);
+ ftp_state(data, FTP_PRET);
}
else
result = ftp_state_use_pasv(data, conn);
@@ -1377,7 +1377,7 @@ static CURLcode ftp_state_rest(struct Curl_easy *data,
whether it supports range */
result = Curl_pp_sendf(data, &ftpc->pp, "REST %d", 0);
if(!result)
- state(data, FTP_REST);
+ ftp_state(data, FTP_REST);
}
else
result = ftp_state_prepare_transfer(data);
@@ -1398,7 +1398,7 @@ static CURLcode ftp_state_size(struct Curl_easy *data,
/* we know ftpc->file is a valid pointer to a file name */
result = Curl_pp_sendf(data, &ftpc->pp, "SIZE %s", ftpc->file);
if(!result)
- state(data, FTP_SIZE);
+ ftp_state(data, FTP_SIZE);
}
else
result = ftp_state_rest(data, conn);
@@ -1466,7 +1466,7 @@ static CURLcode ftp_state_list(struct Curl_easy *data)
free(cmd);
if(!result)
- state(data, FTP_LIST);
+ ftp_state(data, FTP_LIST);
return result;
}
@@ -1530,7 +1530,7 @@ static CURLcode ftp_state_mdtm(struct Curl_easy *data)
result = Curl_pp_sendf(data, &ftpc->pp, "MDTM %s", ftpc->file);
if(!result)
- state(data, FTP_MDTM);
+ ftp_state(data, FTP_MDTM);
}
else
result = ftp_state_type(data);
@@ -1569,7 +1569,7 @@ static CURLcode ftp_state_ul_setup(struct Curl_easy *data,
/* Got no given size to start from, figure it out */
result = Curl_pp_sendf(data, &ftpc->pp, "SIZE %s", ftpc->file);
if(!result)
- state(data, FTP_STOR_SIZE);
+ ftp_state(data, FTP_STOR_SIZE);
return result;
}
@@ -1624,7 +1624,7 @@ static CURLcode ftp_state_ul_setup(struct Curl_easy *data,
* ftp_done() because we didn't transfer anything! */
ftp->transfer = PPTRANSFER_NONE;
- state(data, FTP_STOP);
+ ftp_state(data, FTP_STOP);
return CURLE_OK;
}
}
@@ -1634,7 +1634,7 @@ static CURLcode ftp_state_ul_setup(struct Curl_easy *data,
result = Curl_pp_sendf(data, &ftpc->pp, append?"APPE %s":"STOR %s",
ftpc->file);
if(!result)
- state(data, FTP_STOR);
+ ftp_state(data, FTP_STOR);
return result;
}
@@ -1695,7 +1695,7 @@ static CURLcode ftp_state_quote(struct Curl_easy *data,
result = Curl_pp_sendf(data, &ftpc->pp, "%s", cmd);
if(result)
return result;
- state(data, instate);
+ ftp_state(data, instate);
quote = TRUE;
}
}
@@ -1709,7 +1709,7 @@ static CURLcode ftp_state_quote(struct Curl_easy *data,
break;
case FTP_RETR_PREQUOTE:
if(ftp->transfer != PPTRANSFER_BODY)
- state(data, FTP_STOP);
+ ftp_state(data, FTP_STOP);
else {
if(ftpc->known_filesize != -1) {
Curl_pgrsSetDownloadSize(data, ftpc->known_filesize);
@@ -1731,12 +1731,12 @@ static CURLcode ftp_state_quote(struct Curl_easy *data,
*/
result = Curl_pp_sendf(data, &ftpc->pp, "RETR %s", ftpc->file);
if(!result)
- state(data, FTP_RETR);
+ ftp_state(data, FTP_RETR);
}
else {
result = Curl_pp_sendf(data, &ftpc->pp, "SIZE %s", ftpc->file);
if(!result)
- state(data, FTP_RETR_SIZE);
+ ftp_state(data, FTP_RETR_SIZE);
}
}
}
@@ -1780,7 +1780,7 @@ static CURLcode ftp_epsv_disable(struct Curl_easy *data,
if(!result) {
conn->proto.ftpc.count1++;
/* remain in/go to the FTP_PASV state */
- state(data, FTP_PASV);
+ ftp_state(data, FTP_PASV);
}
return result;
}
@@ -2005,7 +2005,7 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data,
return CURLE_OUT_OF_MEMORY;
conn->bits.do_more = TRUE;
- state(data, FTP_STOP); /* this phase is completed */
+ ftp_state(data, FTP_STOP); /* this phase is completed */
return result;
}
@@ -2039,7 +2039,7 @@ static CURLcode ftp_state_port_resp(struct Curl_easy *data,
}
else {
infof(data, "Connect data stream actively");
- state(data, FTP_STOP); /* end of DO phase */
+ ftp_state(data, FTP_STOP); /* end of DO phase */
result = ftp_dophase_done(data, FALSE);
}
@@ -2151,7 +2151,7 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
infof(data, "The requested document is not new enough");
ftp->transfer = PPTRANSFER_NONE; /* mark to not transfer data */
data->info.timecond = TRUE;
- state(data, FTP_STOP);
+ ftp_state(data, FTP_STOP);
return CURLE_OK;
}
break;
@@ -2160,7 +2160,7 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
infof(data, "The requested document is not old enough");
ftp->transfer = PPTRANSFER_NONE; /* mark to not transfer data */
data->info.timecond = TRUE;
- state(data, FTP_STOP);
+ ftp_state(data, FTP_STOP);
return CURLE_OK;
}
break;
@@ -2268,7 +2268,7 @@ static CURLcode ftp_state_retr(struct Curl_easy *data,
/* Set ->transfer so that we won't get any error in ftp_done()
* because we didn't transfer the any file */
ftp->transfer = PPTRANSFER_NONE;
- state(data, FTP_STOP);
+ ftp_state(data, FTP_STOP);
return CURLE_OK;
}
@@ -2279,13 +2279,13 @@ static CURLcode ftp_state_retr(struct Curl_easy *data,
result = Curl_pp_sendf(data, &ftpc->pp, "REST %" CURL_FORMAT_CURL_OFF_T,
data->state.resume_from);
if(!result)
- state(data, FTP_RETR_REST);
+ ftp_state(data, FTP_RETR_REST);
}
else {
/* no resume */
result = Curl_pp_sendf(data, &ftpc->pp, "RETR %s", ftpc->file);
if(!result)
- state(data, FTP_RETR);
+ ftp_state(data, FTP_RETR);
}
return result;
@@ -2385,7 +2385,7 @@ static CURLcode ftp_state_rest_resp(struct Curl_easy *data,
else {
result = Curl_pp_sendf(data, &ftpc->pp, "RETR %s", ftpc->file);
if(!result)
- state(data, FTP_RETR);
+ ftp_state(data, FTP_RETR);
}
break;
}
@@ -2401,7 +2401,7 @@ static CURLcode ftp_state_stor_resp(struct Curl_easy *data,
if(ftpcode >= 400) {
failf(data, "Failed FTP upload: %0d", ftpcode);
- state(data, FTP_STOP);
+ ftp_state(data, FTP_STOP);
/* oops, we never close the sockets! */
return CURLE_UPLOAD_FAILED;
}
@@ -2412,7 +2412,7 @@ static CURLcode ftp_state_stor_resp(struct Curl_easy *data,
if(data->set.ftp_use_port) {
bool connected;
- state(data, FTP_STOP); /* no longer in STOR state */
+ ftp_state(data, FTP_STOP); /* no longer in STOR state */
result = AllowServerConnect(data, &connected);
if(result)
@@ -2535,7 +2535,7 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data,
if(!connected) {
struct ftp_conn *ftpc = &conn->proto.ftpc;
infof(data, "Data conn was not available immediately");
- state(data, FTP_STOP);
+ ftp_state(data, FTP_STOP);
ftpc->wait_data_conn = TRUE;
}
}
@@ -2546,7 +2546,7 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data,
if((instate == FTP_LIST) && (ftpcode == 450)) {
/* simply no matching files in the dir listing */
ftp->transfer = PPTRANSFER_NONE; /* don't download anything */
- state(data, FTP_STOP); /* this phase is over */
+ ftp_state(data, FTP_STOP); /* this phase is over */
}
else {
failf(data, "RETR response: %03d", ftpcode);
@@ -2582,7 +2582,7 @@ static CURLcode ftp_state_loggedin(struct Curl_easy *data)
*/
result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "PBSZ %d", 0);
if(!result)
- state(data, FTP_PBSZ);
+ ftp_state(data, FTP_PBSZ);
}
else {
result = ftp_state_pwd(data, conn);
@@ -2605,7 +2605,7 @@ static CURLcode ftp_state_user_resp(struct Curl_easy *data,
result = Curl_pp_sendf(data, &ftpc->pp, "PASS %s",
conn->passwd?conn->passwd:"");
if(!result)
- state(data, FTP_PASS);
+ ftp_state(data, FTP_PASS);
}
else if(ftpcode/100 == 2) {
/* 230 User ... logged in.
@@ -2617,7 +2617,7 @@ static CURLcode ftp_state_user_resp(struct Curl_easy *data,
result = Curl_pp_sendf(data, &ftpc->pp, "ACCT %s",
data->set.str[STRING_FTP_ACCOUNT]);
if(!result)
- state(data, FTP_ACCT);
+ ftp_state(data, FTP_ACCT);
}
else {
failf(data, "ACCT requested but none available");
@@ -2638,7 +2638,7 @@ static CURLcode ftp_state_user_resp(struct Curl_easy *data,
data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]);
if(!result) {
ftpc->ftp_trying_alternative = TRUE;
- state(data, FTP_USER);
+ ftp_state(data, FTP_USER);
}
}
else {
@@ -2741,7 +2741,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
result = Curl_pp_sendf(data, &ftpc->pp, "AUTH %s",
ftpauth[ftpc->count1]);
if(!result)
- state(data, FTP_AUTH);
+ ftp_state(data, FTP_AUTH);
}
else
result = ftp_state_user(data, conn);
@@ -2808,7 +2808,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
Curl_pp_sendf(data, &ftpc->pp, "PROT %c",
data->set.use_ssl == CURLUSESSL_CONTROL ? 'C' : 'P');
if(!result)
- state(data, FTP_PROT);
+ ftp_state(data, FTP_PROT);
break;
case FTP_PROT:
@@ -2827,7 +2827,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
*/
result = Curl_pp_sendf(data, &ftpc->pp, "%s", "CCC");
if(!result)
- state(data, FTP_CCC);
+ ftp_state(data, FTP_CCC);
}
else
result = ftp_state_pwd(data, conn);
@@ -2919,7 +2919,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
infof(data, "Entry path is '%s'", ftpc->entrypath);
/* also save it where getinfo can access it: */
data->state.most_recent_ftp_entrypath = ftpc->entrypath;
- state(data, FTP_SYST);
+ ftp_state(data, FTP_SYST);
break;
}
@@ -2935,7 +2935,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
infof(data, "Failed to figure out path");
}
}
- state(data, FTP_STOP); /* we are done with the CONNECT phase! */
+ ftp_state(data, FTP_STOP); /* we are done with the CONNECT phase! */
DEBUGF(infof(data, "protocol connect phase DONE"));
break;
@@ -2970,7 +2970,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
/* remember target server OS */
Curl_safefree(ftpc->server_os);
ftpc->server_os = os;
- state(data, FTP_NAMEFMT);
+ ftp_state(data, FTP_NAMEFMT);
break;
}
/* Nothing special for the target server. */
@@ -2982,7 +2982,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
/* Cannot identify server OS. Continue anyway and cross fingers. */
}
- state(data, FTP_STOP); /* we are done with the CONNECT phase! */
+ ftp_state(data, FTP_STOP); /* we are done with the CONNECT phase! */
DEBUGF(infof(data, "protocol connect phase DONE"));
break;
@@ -2993,7 +2993,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
break;
}
- state(data, FTP_STOP); /* we are done with the CONNECT phase! */
+ ftp_state(data, FTP_STOP); /* we are done with the CONNECT phase! */
DEBUGF(infof(data, "protocol connect phase DONE"));
break;
@@ -3026,7 +3026,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
result = Curl_pp_sendf(data, &ftpc->pp, "MKD %s",
ftpc->dirs[ftpc->cwdcount - 1]);
if(!result)
- state(data, FTP_MKD);
+ ftp_state(data, FTP_MKD);
}
else {
/* return failure */
@@ -3055,7 +3055,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
result = CURLE_REMOTE_ACCESS_DENIED;
}
else {
- state(data, FTP_CWD);
+ ftp_state(data, FTP_CWD);
/* send CWD */
result = Curl_pp_sendf(data, &ftpc->pp, "CWD %s",
ftpc->dirs[ftpc->cwdcount - 1]);
@@ -3114,7 +3114,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
/* fallthrough, just stop! */
default:
/* internal error */
- state(data, FTP_STOP);
+ ftp_state(data, FTP_STOP);
break;
}
} /* if(ftpcode) */
@@ -3191,7 +3191,7 @@ static CURLcode ftp_connect(struct Curl_easy *data,
/* When we connect, we start in the state where we await the 220
response */
- state(data, FTP_WAIT220);
+ ftp_state(data, FTP_WAIT220);
result = ftp_multi_statemach(data, done);
@@ -3516,13 +3516,13 @@ static CURLcode ftp_nb_type(struct Curl_easy *data,
char want = (char)(ascii?'A':'I');
if(ftpc->transfertype == want) {
- state(data, newstate);
+ ftp_state(data, newstate);
return ftp_state_type_resp(data, 200, newstate);
}
result = Curl_pp_sendf(data, &ftpc->pp, "TYPE %c", want);
if(!result) {
- state(data, newstate);
+ ftp_state(data, newstate);
/* keep track of our current transfer type */
ftpc->transfertype = want;
@@ -4040,11 +4040,11 @@ static CURLcode ftp_quit(struct Curl_easy *data, struct connectdata *conn)
curl_easy_strerror(result));
conn->proto.ftpc.ctl_valid = FALSE; /* mark control connection as bad */
connclose(conn, "QUIT command failed"); /* mark for connection closure */
- state(data, FTP_STOP);
+ ftp_state(data, FTP_STOP);
return result;
}
- state(data, FTP_QUIT);
+ ftp_state(data, FTP_QUIT);
result = ftp_block_statemach(data, conn);
}
diff --git a/Utilities/cmcurl/lib/getinfo.c b/Utilities/cmcurl/lib/getinfo.c
index 826ffd0..f1574e0 100644
--- a/Utilities/cmcurl/lib/getinfo.c
+++ b/Utilities/cmcurl/lib/getinfo.c
@@ -415,6 +415,13 @@ static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
case CURLINFO_RETRY_AFTER:
*param_offt = data->info.retry_after;
break;
+ case CURLINFO_XFER_ID:
+ *param_offt = data->id;
+ break;
+ case CURLINFO_CONN_ID:
+ *param_offt = data->conn?
+ data->conn->connection_id : data->state.recent_conn_id;
+ break;
default:
return CURLE_UNKNOWN_OPTION;
}
diff --git a/Utilities/cmcurl/lib/hostip.c b/Utilities/cmcurl/lib/hostip.c
index d721403..1a289de 100644
--- a/Utilities/cmcurl/lib/hostip.c
+++ b/Utilities/cmcurl/lib/hostip.c
@@ -67,10 +67,6 @@
#include "curl_memory.h"
#include "memdebug.h"
-#if defined(ENABLE_IPV6) && defined(CURL_OSX_CALL_COPYPROXIES)
-#include <SystemConfiguration/SCDynamicStoreCopySpecific.h>
-#endif
-
#if defined(CURLRES_SYNCH) && \
defined(HAVE_ALARM) && \
defined(SIGALRM) && \
@@ -561,6 +557,7 @@ static struct Curl_addrinfo *get_localhost6(int port, const char *name)
static struct Curl_addrinfo *get_localhost(int port, const char *name)
{
struct Curl_addrinfo *ca;
+ struct Curl_addrinfo *ca6;
const size_t ss_size = sizeof(struct sockaddr_in);
const size_t hostlen = strlen(name);
struct sockaddr_in sa;
@@ -587,8 +584,12 @@ static struct Curl_addrinfo *get_localhost(int port, const char *name)
memcpy(ca->ai_addr, &sa, ss_size);
ca->ai_canonname = (char *)ca->ai_addr + ss_size;
strcpy(ca->ai_canonname, name);
- ca->ai_next = get_localhost6(port, name);
- return ca;
+
+ ca6 = get_localhost6(port, name);
+ if(!ca6)
+ return ca;
+ ca6->ai_next = ca;
+ return ca6;
}
#ifdef ENABLE_IPV6
@@ -743,23 +744,6 @@ enum resolve_t Curl_resolv(struct Curl_easy *data,
return CURLRESOLV_ERROR;
}
-#if defined(ENABLE_IPV6) && defined(CURL_OSX_CALL_COPYPROXIES)
- {
- /*
- * The automagic conversion from IPv4 literals to IPv6 literals only
- * works if the SCDynamicStoreCopyProxies system function gets called
- * first. As Curl currently doesn't support system-wide HTTP proxies, we
- * therefore don't use any value this function might return.
- *
- * This function is only available on a macOS and is not needed for
- * IPv4-only builds, hence the conditions above.
- */
- CFDictionaryRef dict = SCDynamicStoreCopyProxies(NULL);
- if(dict)
- CFRelease(dict);
- }
-#endif
-
#ifndef USE_RESOLVE_ON_IPS
/* First check if this is an IPv4 address string */
if(Curl_inet_pton(AF_INET, hostname, &in) > 0)
diff --git a/Utilities/cmcurl/lib/hsts.c b/Utilities/cmcurl/lib/hsts.c
index 53c01fc..7ecf004 100644
--- a/Utilities/cmcurl/lib/hsts.c
+++ b/Utilities/cmcurl/lib/hsts.c
@@ -57,7 +57,7 @@
/* to play well with debug builds, we can *set* a fixed time this will
return */
time_t deltatime; /* allow for "adjustments" for unit test purposes */
-static time_t debugtime(void *unused)
+static time_t hsts_debugtime(void *unused)
{
char *timestr = getenv("CURL_TIME");
(void)unused;
@@ -70,7 +70,8 @@ static time_t debugtime(void *unused)
}
return time(NULL);
}
-#define time(x) debugtime(x)
+#undef time
+#define time(x) hsts_debugtime(x)
#endif
struct hsts *Curl_hsts_init(void)
diff --git a/Utilities/cmcurl/lib/http.c b/Utilities/cmcurl/lib/http.c
index 219dcc2..e611d27 100644
--- a/Utilities/cmcurl/lib/http.c
+++ b/Utilities/cmcurl/lib/http.c
@@ -1308,7 +1308,7 @@ CURLcode Curl_buffer_send(struct dynbuf *in,
|| IS_HTTPS_PROXY(conn->http_proxy.proxytype)
#endif
)
- && conn->httpversion != 20) {
+ && conn->httpversion < 20) {
/* Make sure this doesn't send more body bytes than what the max send
speed says. The request bytes do not count to the max speed.
*/
@@ -2667,11 +2667,7 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn,
#ifndef USE_HYPER
/* With Hyper the body is always passed on separately */
if(data->set.postfields) {
-
- /* In HTTP2, we send request body in DATA frame regardless of
- its size. */
- if(conn->httpversion < 20 &&
- !data->state.expect100header &&
+ if(!data->state.expect100header &&
(http->postsize < MAX_INITIAL_POST_SIZE)) {
/* if we don't use expect: 100 AND
postsize is less than MAX_INITIAL_POST_SIZE
@@ -2832,16 +2828,18 @@ CURLcode Curl_http_cookies(struct Curl_easy *data,
}
if(co) {
struct Cookie *store = co;
+ size_t clen = 8; /* hold the size of the generated Cookie: header */
/* now loop through all cookies that matched */
while(co) {
if(co->value) {
- if(0 == count) {
+ size_t add;
+ if(!count) {
result = Curl_dyn_addn(r, STRCONST("Cookie: "));
if(result)
break;
}
- if((Curl_dyn_len(r) + strlen(co->name) + strlen(co->value) + 1) >=
- MAX_COOKIE_HEADER_LEN) {
+ add = strlen(co->name) + strlen(co->value) + 1;
+ if(clen + add >= MAX_COOKIE_HEADER_LEN) {
infof(data, "Restricted outgoing cookies due to header size, "
"'%s' not sent", co->name);
linecap = TRUE;
@@ -2851,6 +2849,7 @@ CURLcode Curl_http_cookies(struct Curl_easy *data,
co->name, co->value);
if(result)
break;
+ clen += add + (count ? 2 : 0);
count++;
}
co = co->next; /* next cookie please */
@@ -3381,6 +3380,9 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
}
}
+ if(data->req.upload_done)
+ Curl_conn_ev_data_done_send(data);
+
if((conn->httpversion >= 20) && data->req.upload_chunky)
/* upload_chunky was set above to set up the request in a chunky fashion,
but is disabled here again to avoid that the chunked encoded version is
@@ -4569,8 +4571,8 @@ CURLcode Curl_http_req_make(struct httpreq **preq,
if(!req->path)
goto out;
}
- Curl_dynhds_init(&req->headers, 0, DYN_H2_HEADERS);
- Curl_dynhds_init(&req->trailers, 0, DYN_H2_TRAILERS);
+ Curl_dynhds_init(&req->headers, 0, DYN_HTTP_REQUEST);
+ Curl_dynhds_init(&req->trailers, 0, DYN_HTTP_REQUEST);
result = CURLE_OK;
out:
@@ -4727,8 +4729,8 @@ CURLcode Curl_http_req_make2(struct httpreq **preq,
if(result)
goto out;
- Curl_dynhds_init(&req->headers, 0, DYN_H2_HEADERS);
- Curl_dynhds_init(&req->trailers, 0, DYN_H2_TRAILERS);
+ Curl_dynhds_init(&req->headers, 0, DYN_HTTP_REQUEST);
+ Curl_dynhds_init(&req->trailers, 0, DYN_HTTP_REQUEST);
result = CURLE_OK;
out:
@@ -4858,8 +4860,8 @@ CURLcode Curl_http_resp_make(struct http_resp **presp,
if(!resp->description)
goto out;
}
- Curl_dynhds_init(&resp->headers, 0, DYN_H2_HEADERS);
- Curl_dynhds_init(&resp->trailers, 0, DYN_H2_TRAILERS);
+ Curl_dynhds_init(&resp->headers, 0, DYN_HTTP_REQUEST);
+ Curl_dynhds_init(&resp->trailers, 0, DYN_HTTP_REQUEST);
result = CURLE_OK;
out:
diff --git a/Utilities/cmcurl/lib/http1.c b/Utilities/cmcurl/lib/http1.c
index 46fe855..a442d3e 100644
--- a/Utilities/cmcurl/lib/http1.c
+++ b/Utilities/cmcurl/lib/http1.c
@@ -38,124 +38,97 @@
#include "memdebug.h"
-#define MAX_URL_LEN (4*1024)
+#define H1_MAX_URL_LEN (8*1024)
void Curl_h1_req_parse_init(struct h1_req_parser *parser, size_t max_line_len)
{
memset(parser, 0, sizeof(*parser));
parser->max_line_len = max_line_len;
- Curl_bufq_init(&parser->scratch, max_line_len, 1);
+ Curl_dyn_init(&parser->scratch, max_line_len);
}
void Curl_h1_req_parse_free(struct h1_req_parser *parser)
{
if(parser) {
Curl_http_req_free(parser->req);
- Curl_bufq_free(&parser->scratch);
+ Curl_dyn_free(&parser->scratch);
parser->req = NULL;
parser->done = FALSE;
}
}
+static CURLcode trim_line(struct h1_req_parser *parser, int options)
+{
+ DEBUGASSERT(parser->line);
+ if(parser->line_len) {
+ if(parser->line[parser->line_len - 1] == '\n')
+ --parser->line_len;
+ if(parser->line_len) {
+ if(parser->line[parser->line_len - 1] == '\r')
+ --parser->line_len;
+ else if(options & H1_PARSE_OPT_STRICT)
+ return CURLE_URL_MALFORMAT;
+ }
+ else if(options & H1_PARSE_OPT_STRICT)
+ return CURLE_URL_MALFORMAT;
+ }
+ else if(options & H1_PARSE_OPT_STRICT)
+ return CURLE_URL_MALFORMAT;
+
+ if(parser->line_len > parser->max_line_len) {
+ return CURLE_URL_MALFORMAT;
+ }
+ return CURLE_OK;
+}
+
static ssize_t detect_line(struct h1_req_parser *parser,
- const char *buf, const size_t buflen, int options,
+ const char *buf, const size_t buflen,
CURLcode *err)
{
const char *line_end;
- size_t len;
DEBUGASSERT(!parser->line);
line_end = memchr(buf, '\n', buflen);
if(!line_end) {
- *err = (buflen > parser->max_line_len)? CURLE_URL_MALFORMAT : CURLE_AGAIN;
+ *err = CURLE_AGAIN;
return -1;
}
- len = line_end - buf + 1;
- if(len > parser->max_line_len) {
- *err = CURLE_URL_MALFORMAT;
- return -1;
- }
-
- if(options & H1_PARSE_OPT_STRICT) {
- if((len == 1) || (buf[len - 2] != '\r')) {
- *err = CURLE_URL_MALFORMAT;
- return -1;
- }
- parser->line = buf;
- parser->line_len = len - 2;
- }
- else {
- parser->line = buf;
- parser->line_len = len - (((len == 1) || (buf[len - 2] != '\r'))? 1 : 2);
- }
+ parser->line = buf;
+ parser->line_len = line_end - buf + 1;
*err = CURLE_OK;
- return (ssize_t)len;
+ return (ssize_t)parser->line_len;
}
static ssize_t next_line(struct h1_req_parser *parser,
const char *buf, const size_t buflen, int options,
CURLcode *err)
{
- ssize_t nread = 0, n;
+ ssize_t nread = 0;
if(parser->line) {
- if(parser->scratch_skip) {
- /* last line was from scratch. Remove it now, since we are done
- * with it and look for the next one. */
- Curl_bufq_skip_and_shift(&parser->scratch, parser->scratch_skip);
- parser->scratch_skip = 0;
- }
parser->line = NULL;
parser->line_len = 0;
+ Curl_dyn_reset(&parser->scratch);
}
- if(Curl_bufq_is_empty(&parser->scratch)) {
- nread = detect_line(parser, buf, buflen, options, err);
- if(nread < 0) {
- if(*err != CURLE_AGAIN)
+ nread = detect_line(parser, buf, buflen, err);
+ if(nread >= 0) {
+ if(Curl_dyn_len(&parser->scratch)) {
+ /* append detected line to scratch to have the complete line */
+ *err = Curl_dyn_addn(&parser->scratch, parser->line, parser->line_len);
+ if(*err)
return -1;
- /* not a complete line, add to scratch for later revisit */
- nread = Curl_bufq_write(&parser->scratch,
- (const unsigned char *)buf, buflen, err);
- return nread;
+ parser->line = Curl_dyn_ptr(&parser->scratch);
+ parser->line_len = Curl_dyn_len(&parser->scratch);
}
- /* found one */
+ *err = trim_line(parser, options);
+ if(*err)
+ return -1;
}
- else {
- const char *sbuf;
- size_t sbuflen;
-
- /* scratch contains bytes from last attempt, add more to it */
- if(buflen) {
- const char *line_end;
- size_t add_len;
- ssize_t pos;
-
- line_end = memchr(buf, '\n', buflen);
- pos = line_end? (line_end - buf + 1) : -1;
- add_len = (pos >= 0)? (size_t)pos : buflen;
- nread = Curl_bufq_write(&parser->scratch,
- (const unsigned char *)buf, add_len, err);
- if(nread < 0) {
- /* Unable to add anything to scratch is an error, since we should
- * have seen a line there then before. */
- if(*err == CURLE_AGAIN)
- *err = CURLE_URL_MALFORMAT;
- return -1;
- }
- }
-
- if(Curl_bufq_peek(&parser->scratch,
- (const unsigned char **)&sbuf, &sbuflen)) {
- n = detect_line(parser, sbuf, sbuflen, options, err);
- if(n < 0 && *err != CURLE_AGAIN)
- return -1; /* real error */
- parser->scratch_skip = (size_t)n;
- }
- else {
- /* we SHOULD be able to peek at scratch data */
- DEBUGASSERT(0);
- }
+ else if(*err == CURLE_AGAIN) {
+ /* no line end in `buf`, add it to our scratch */
+ *err = Curl_dyn_addn(&parser->scratch, (const unsigned char *)buf, buflen);
+ nread = (*err)? -1 : (ssize_t)buflen;
}
return nread;
}
@@ -231,7 +204,7 @@ static CURLcode start_req(struct h1_req_parser *parser,
else {
/* origin-form OR absolute-form */
CURLUcode uc;
- char tmp[MAX_URL_LEN];
+ char tmp[H1_MAX_URL_LEN];
/* default, unless we see an absolute URL */
path = target;
@@ -328,7 +301,7 @@ ssize_t Curl_h1_req_parse_read(struct h1_req_parser *parser,
goto out;
}
parser->done = TRUE;
- Curl_bufq_free(&parser->scratch);
+ Curl_dyn_reset(&parser->scratch);
/* last chance adjustments */
}
else {
diff --git a/Utilities/cmcurl/lib/http1.h b/Utilities/cmcurl/lib/http1.h
index 93111ef..b1eaa96 100644
--- a/Utilities/cmcurl/lib/http1.h
+++ b/Utilities/cmcurl/lib/http1.h
@@ -33,11 +33,11 @@
#define H1_PARSE_OPT_NONE (0)
#define H1_PARSE_OPT_STRICT (1 << 0)
-#define H1_PARSE_DEFAULT_MAX_LINE_LEN (8 * 1024)
+#define H1_PARSE_DEFAULT_MAX_LINE_LEN DYN_HTTP_REQUEST
struct h1_req_parser {
struct httpreq *req;
- struct bufq scratch;
+ struct dynbuf scratch;
size_t scratch_skip;
const char *line;
size_t max_line_len;
diff --git a/Utilities/cmcurl/lib/http2.c b/Utilities/cmcurl/lib/http2.c
index 191d8cd..6c09ec1 100644
--- a/Utilities/cmcurl/lib/http2.c
+++ b/Utilities/cmcurl/lib/http2.c
@@ -134,9 +134,11 @@ struct cf_h2_ctx {
BIT(conn_closed);
BIT(goaway);
BIT(enable_push);
+ BIT(nw_out_blocked);
};
/* How to access `call_data` from a cf_h2 filter */
+#undef CF_CTX_CALL_DATA
#define CF_CTX_CALL_DATA(cf) \
((struct cf_h2_ctx *)(cf)->ctx)->call_data
@@ -175,6 +177,7 @@ struct stream_ctx {
struct bufq sendbuf; /* request buffer */
struct dynhds resp_trailers; /* response trailer fields */
size_t resp_hds_len; /* amount of response header bytes in recvbuf */
+ size_t upload_blocked_len;
curl_off_t upload_left; /* number of request bytes left to upload */
char **push_headers; /* allocated array */
@@ -183,6 +186,7 @@ struct stream_ctx {
int status_code; /* HTTP response status code */
uint32_t error; /* stream error code */
+ uint32_t local_window_size; /* the local recv window size */
bool closed; /* TRUE on stream close */
bool reset; /* TRUE on stream reset */
bool close_handled; /* TRUE if stream closure is handled by libcurl */
@@ -209,9 +213,12 @@ static void drain_stream(struct Curl_cfilter *cf,
(void)cf;
bits = CURL_CSELECT_IN;
- if(!stream->send_closed && stream->upload_left)
+ if(!stream->send_closed &&
+ (stream->upload_left || stream->upload_blocked_len))
bits |= CURL_CSELECT_OUT;
if(data->state.dselect_bits != bits) {
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] DRAIN dselect_bits=%x",
+ stream->id, bits));
data->state.dselect_bits = bits;
Curl_expire(data, 0, EXPIRE_RUN_NOW);
}
@@ -245,13 +252,14 @@ static CURLcode http2_data_setup(struct Curl_cfilter *cf,
H2_STREAM_SEND_CHUNKS, BUFQ_OPT_NONE);
Curl_bufq_initp(&stream->recvbuf, &ctx->stream_bufcp,
H2_STREAM_RECV_CHUNKS, BUFQ_OPT_SOFT_LIMIT);
- Curl_dynhds_init(&stream->resp_trailers, 0, DYN_H2_TRAILERS);
+ Curl_dynhds_init(&stream->resp_trailers, 0, DYN_HTTP_REQUEST);
stream->resp_hds_len = 0;
stream->bodystarted = FALSE;
stream->status_code = -1;
stream->closed = FALSE;
stream->close_handled = FALSE;
stream->error = NGHTTP2_NO_ERROR;
+ stream->local_window_size = H2_STREAM_WINDOW_SIZE;
stream->upload_left = 0;
H2_STREAM_LCTX(data) = stream;
@@ -580,7 +588,6 @@ static bool http2_connisalive(struct Curl_cfilter *cf, struct Curl_easy *data,
ssize_t nread = -1;
*input_pending = FALSE;
- Curl_attach_connection(data, cf->conn);
nread = Curl_bufq_slurp(&ctx->inbufq, nw_in_reader, cf, &result);
if(nread != -1) {
DEBUGF(LOG_CF(data, cf, "%zd bytes stray data read before trying "
@@ -592,11 +599,10 @@ static bool http2_connisalive(struct Curl_cfilter *cf, struct Curl_easy *data,
alive = !should_close_session(ctx);
}
}
- else {
+ else if(result != CURLE_AGAIN) {
/* the read failed so let's say this is dead anyway */
alive = FALSE;
}
- Curl_detach_connection(data);
}
return alive;
@@ -644,13 +650,17 @@ static CURLcode nw_out_flush(struct Curl_cfilter *cf,
if(Curl_bufq_is_empty(&ctx->outbufq))
return CURLE_OK;
- DEBUGF(LOG_CF(data, cf, "h2 conn flush %zu bytes",
- Curl_bufq_len(&ctx->outbufq)));
nwritten = Curl_bufq_pass(&ctx->outbufq, nw_out_writer, cf, &result);
- if(nwritten < 0 && result != CURLE_AGAIN) {
+ if(nwritten < 0) {
+ if(result == CURLE_AGAIN) {
+ DEBUGF(LOG_CF(data, cf, "flush nw send buffer(%zu) -> EAGAIN",
+ Curl_bufq_len(&ctx->outbufq)));
+ ctx->nw_out_blocked = 1;
+ }
return result;
}
- return CURLE_OK;
+ DEBUGF(LOG_CF(data, cf, "nw send buffer flushed"));
+ return Curl_bufq_is_empty(&ctx->outbufq)? CURLE_OK: CURLE_AGAIN;
}
/*
@@ -676,15 +686,17 @@ static ssize_t send_callback(nghttp2_session *h2,
nw_out_writer, cf, &result);
if(nwritten < 0) {
if(result == CURLE_AGAIN) {
+ ctx->nw_out_blocked = 1;
return NGHTTP2_ERR_WOULDBLOCK;
}
failf(data, "Failed sending HTTP2 data");
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
- if(!nwritten)
+ if(!nwritten) {
+ ctx->nw_out_blocked = 1;
return NGHTTP2_ERR_WOULDBLOCK;
-
+ }
return nwritten;
}
@@ -964,6 +976,7 @@ static CURLcode on_stream_frame(struct Curl_cfilter *cf,
struct stream_ctx *stream = H2_STREAM_CTX(data);
int32_t stream_id = frame->hd.stream_id;
CURLcode result;
+ size_t rbuflen;
int rv;
if(!stream) {
@@ -973,10 +986,10 @@ static CURLcode on_stream_frame(struct Curl_cfilter *cf,
switch(frame->hd.type) {
case NGHTTP2_DATA:
+ rbuflen = Curl_bufq_len(&stream->recvbuf);
DEBUGF(LOG_CF(data, cf, "[h2sid=%d] FRAME[DATA len=%zu pad=%zu], "
"buffered=%zu, window=%d/%d",
- stream_id, frame->hd.length, frame->data.padlen,
- Curl_bufq_len(&stream->recvbuf),
+ stream_id, frame->hd.length, frame->data.padlen, rbuflen,
nghttp2_session_get_stream_effective_recv_data_length(
ctx->h2, stream->id),
nghttp2_session_get_stream_effective_local_window_size(
@@ -993,6 +1006,20 @@ static CURLcode on_stream_frame(struct Curl_cfilter *cf,
if(frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
drain_stream(cf, data, stream);
}
+ else if(rbuflen > stream->local_window_size) {
+ int32_t wsize = nghttp2_session_get_stream_local_window_size(
+ ctx->h2, stream->id);
+ if(wsize > 0 && (uint32_t)wsize != stream->local_window_size) {
+ /* H2 flow control is not absolute, as the server might not have the
+ * same view, yet. When we recieve more than we want, we enforce
+ * the local window size again to make nghttp2 send WINDOW_UPATEs
+ * accordingly. */
+ nghttp2_session_set_local_window_size(ctx->h2,
+ NGHTTP2_FLAG_NONE,
+ stream->id,
+ stream->local_window_size);
+ }
+ }
break;
case NGHTTP2_HEADERS:
DEBUGF(LOG_CF(data, cf, "[h2sid=%d] FRAME[HEADERS]", stream_id));
@@ -1095,6 +1122,21 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
ctx->max_concurrent_streams));
multi_connchanged(data->multi);
}
+ /* Since the initial stream window is 64K, a request might be on HOLD,
+ * due to exhaustion. The (initial) SETTINGS may announce a much larger
+ * window and *assume* that we treat this like a WINDOW_UPDATE. Some
+ * servers send an explicit WINDOW_UPDATE, but not all seem to do that.
+ * To be safe, we UNHOLD a stream in order not to stall. */
+ if((data->req.keepon & KEEP_SEND_HOLD) &&
+ (data->req.keepon & KEEP_SEND)) {
+ struct stream_ctx *stream = H2_STREAM_CTX(data);
+ data->req.keepon &= ~KEEP_SEND_HOLD;
+ if(stream) {
+ drain_stream(cf, data, stream);
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] un-holding after SETTINGS",
+ stream_id));
+ }
+ }
break;
}
case NGHTTP2_GOAWAY:
@@ -1448,8 +1490,8 @@ static ssize_t req_body_read_callback(nghttp2_session *session,
if(nread > 0 && stream->upload_left != -1)
stream->upload_left -= nread;
- DEBUGF(LOG_CF(data_s, cf, "[h2sid=%d] req_body_read(len=%zu) left=%zd"
- " -> %zd, %d",
+ DEBUGF(LOG_CF(data_s, cf, "[h2sid=%d] req_body_read(len=%zu) left=%"
+ CURL_FORMAT_CURL_OFF_T " -> %zd, %d",
stream_id, length, stream->upload_left, nread, result));
if(stream->upload_left == 0)
@@ -1555,11 +1597,6 @@ static ssize_t http2_handle_stream_close(struct Curl_cfilter *cf,
*err = CURLE_SEND_ERROR; /* trigger Curl_retry_request() later */
return -1;
}
- else if(stream->reset) {
- failf(data, "HTTP/2 stream %u was reset", stream->id);
- *err = stream->bodystarted? CURLE_PARTIAL_FILE : CURLE_RECV_ERROR;
- return -1;
- }
else if(stream->error != NGHTTP2_NO_ERROR) {
failf(data, "HTTP/2 stream %u was not closed cleanly: %s (err %u)",
stream->id, nghttp2_http2_strerror(stream->error),
@@ -1567,6 +1604,11 @@ static ssize_t http2_handle_stream_close(struct Curl_cfilter *cf,
*err = CURLE_HTTP2_STREAM;
return -1;
}
+ else if(stream->reset) {
+ failf(data, "HTTP/2 stream %u was reset", stream->id);
+ *err = stream->bodystarted? CURLE_PARTIAL_FILE : CURLE_RECV_ERROR;
+ return -1;
+ }
if(!stream->bodystarted) {
failf(data, "HTTP/2 stream %u was closed cleanly, but before getting "
@@ -1659,9 +1701,10 @@ static CURLcode h2_progress_egress(struct Curl_cfilter *cf,
struct stream_ctx *stream = H2_STREAM_CTX(data);
int rv = 0;
- if((sweight_wanted(data) != sweight_in_effect(data)) ||
- (data->set.priority.exclusive != data->state.priority.exclusive) ||
- (data->set.priority.parent != data->state.priority.parent) ) {
+ if(stream && stream->id > 0 &&
+ ((sweight_wanted(data) != sweight_in_effect(data)) ||
+ (data->set.priority.exclusive != data->state.priority.exclusive) ||
+ (data->set.priority.parent != data->state.priority.parent)) ) {
/* send new weight and/or dependency */
nghttp2_priority_spec pri_spec;
@@ -1675,7 +1718,8 @@ static CURLcode h2_progress_egress(struct Curl_cfilter *cf,
goto out;
}
- while(!rv && nghttp2_session_want_write(ctx->h2))
+ ctx->nw_out_blocked = 0;
+ while(!rv && !ctx->nw_out_blocked && nghttp2_session_want_write(ctx->h2))
rv = nghttp2_session_send(ctx->h2);
out:
@@ -1739,7 +1783,7 @@ static CURLcode h2_progress_ingress(struct Curl_cfilter *cf,
/* Process network input buffer fist */
if(!Curl_bufq_is_empty(&ctx->inbufq)) {
- DEBUGF(LOG_CF(data, cf, "Process %zd bytes in connection buffer",
+ DEBUGF(LOG_CF(data, cf, "Process %zu bytes in connection buffer",
Curl_bufq_len(&ctx->inbufq)));
if(h2_process_pending_input(cf, data, &result) < 0)
return result;
@@ -1760,7 +1804,7 @@ static CURLcode h2_progress_ingress(struct Curl_cfilter *cf,
}
nread = Curl_bufq_slurp(&ctx->inbufq, nw_in_reader, cf, &result);
- /* DEBUGF(LOG_CF(data, cf, "read %zd bytes nw data -> %zd, %d",
+ /* DEBUGF(LOG_CF(data, cf, "read %zu bytes nw data -> %zd, %d",
Curl_bufq_len(&ctx->inbufq), nread, result)); */
if(nread < 0) {
if(result != CURLE_AGAIN) {
@@ -1836,7 +1880,7 @@ static ssize_t cf_h2_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
out:
result = h2_progress_egress(cf, data);
- if(result) {
+ if(result && result != CURLE_AGAIN) {
*err = result;
nread = -1;
}
@@ -1864,7 +1908,8 @@ static ssize_t h2_submit(struct stream_ctx **pstream,
struct h1_req_parser h1;
struct dynhds h2_headers;
nghttp2_nv *nva = NULL;
- size_t nheader, i;
+ const void *body = NULL;
+ size_t nheader, bodylen, i;
nghttp2_data_provider data_prd;
int32_t stream_id;
nghttp2_priority_spec pri_spec;
@@ -1929,8 +1974,8 @@ static ssize_t h2_submit(struct stream_ctx **pstream,
h2_pri_spec(data, &pri_spec);
- DEBUGF(LOG_CF(data, cf, "send request allowed %d (easy handle %p)",
- nghttp2_session_check_request_allowed(ctx->h2), (void *)data));
+ DEBUGF(LOG_CF(data, cf, "send request allowed %d",
+ nghttp2_session_check_request_allowed(ctx->h2)));
switch(data->state.httpreq) {
case HTTPREQ_POST:
@@ -1966,9 +2011,35 @@ static ssize_t h2_submit(struct stream_ctx **pstream,
DEBUGF(LOG_CF(data, cf, "[h2sid=%d] cf_send(len=%zu) submit %s",
stream_id, len, data->state.url));
- infof(data, "Using Stream ID: %u (easy handle %p)",
- stream_id, (void *)data);
+ infof(data, "Using Stream ID: %u", stream_id);
stream->id = stream_id;
+ stream->local_window_size = H2_STREAM_WINDOW_SIZE;
+ if(data->set.max_recv_speed) {
+ /* We are asked to only receive `max_recv_speed` bytes per second.
+ * Let's limit our stream window size around that, otherwise the server
+ * will send in large bursts only. We make the window 50% larger to
+ * allow for data in flight and avoid stalling. */
+ curl_off_t n = (((data->set.max_recv_speed - 1) / H2_CHUNK_SIZE) + 1);
+ n += CURLMAX((n/2), 1);
+ if(n < (H2_STREAM_WINDOW_SIZE / H2_CHUNK_SIZE) &&
+ n < (UINT_MAX / H2_CHUNK_SIZE)) {
+ stream->local_window_size = (uint32_t)n * H2_CHUNK_SIZE;
+ }
+ }
+
+ body = (const char *)buf + nwritten;
+ bodylen = len - nwritten;
+
+ if(bodylen) {
+ /* We have request body to send in DATA frame */
+ ssize_t n = Curl_bufq_write(&stream->sendbuf, body, bodylen, err);
+ if(n < 0) {
+ *err = CURLE_SEND_ERROR;
+ nwritten = -1;
+ goto out;
+ }
+ nwritten += n;
+ }
out:
DEBUGF(LOG_CF(data, cf, "[h2sid=%d] submit -> %zd, %d",
@@ -1982,17 +2053,13 @@ out:
static ssize_t cf_h2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
const void *buf, size_t len, CURLcode *err)
{
- /*
- * Currently, we send request in this function, but this function is also
- * used to send request body. It would be nice to add dedicated function for
- * request.
- */
struct cf_h2_ctx *ctx = cf->ctx;
struct stream_ctx *stream = H2_STREAM_CTX(data);
struct cf_call_data save;
int rv;
ssize_t nwritten;
CURLcode result;
+ int blocked = 0;
CF_DATA_SAVE(save, cf, data);
@@ -2007,18 +2074,35 @@ static ssize_t cf_h2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
nwritten = http2_handle_stream_close(cf, data, stream, err);
goto out;
}
- /* If stream_id != -1, we have dispatched request HEADERS, and now
- are going to send or sending request body in DATA frame */
- nwritten = Curl_bufq_write(&stream->sendbuf, buf, len, err);
- if(nwritten < 0) {
- if(*err != CURLE_AGAIN)
+ else if(stream->upload_blocked_len) {
+ /* the data in `buf` has alread been submitted or added to the
+ * buffers, but have been EAGAINed on the last invocation. */
+ DEBUGASSERT(len >= stream->upload_blocked_len);
+ if(len < stream->upload_blocked_len) {
+ /* Did we get called again with a smaller `len`? This should not
+ * happend. We are not prepared to handle that. */
+ failf(data, "HTTP/2 send again with decreased length");
+ *err = CURLE_HTTP2;
+ nwritten = -1;
goto out;
- nwritten = 0;
+ }
+ nwritten = (ssize_t)stream->upload_blocked_len;
+ stream->upload_blocked_len = 0;
+ }
+ else {
+ /* If stream_id != -1, we have dispatched request HEADERS and
+ * optionally request body, and now are going to send or sending
+ * more request body in DATA frame */
+ nwritten = Curl_bufq_write(&stream->sendbuf, buf, len, err);
+ if(nwritten < 0) {
+ if(*err != CURLE_AGAIN)
+ goto out;
+ nwritten = 0;
+ }
}
- DEBUGF(LOG_CF(data, cf, "[h2sid=%u] bufq_write(len=%zu) -> %zd, %d",
- stream->id, len, nwritten, *err));
if(!Curl_bufq_is_empty(&stream->sendbuf)) {
+ /* req body data is buffered, resume the potentially suspended stream */
rv = nghttp2_session_resume_data(ctx->h2, stream->id);
if(nghttp2_is_fatal(rv)) {
*err = CURLE_SEND_ERROR;
@@ -2026,104 +2110,99 @@ static ssize_t cf_h2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
goto out;
}
}
-
- result = h2_progress_ingress(cf, data);
- if(result) {
- *err = result;
- nwritten = -1;
- goto out;
- }
-
- result = h2_progress_egress(cf, data);
- if(result) {
- *err = result;
- nwritten = -1;
- goto out;
- }
-
- if(should_close_session(ctx)) {
- if(stream->closed) {
- nwritten = http2_handle_stream_close(cf, data, stream, err);
- }
- else {
- DEBUGF(LOG_CF(data, cf, "send: nothing to do in this session"));
- *err = CURLE_HTTP2;
- nwritten = -1;
- }
- goto out;
- }
-
- if(!nwritten) {
- size_t rwin = nghttp2_session_get_stream_remote_window_size(ctx->h2,
- stream->id);
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] cf_send: win %u/%zu",
- stream->id,
- nghttp2_session_get_remote_window_size(ctx->h2), rwin));
- if(rwin == 0) {
- /* We cannot upload more as the stream's remote window size
- * is 0. We need to receive WIN_UPDATEs before we can continue.
- */
- data->req.keepon |= KEEP_SEND_HOLD;
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] holding send as remote flow "
- "window is exhausted", stream->id));
- }
- nwritten = -1;
- *err = CURLE_AGAIN;
- }
- /* handled writing BODY for open stream. */
- goto out;
}
else {
nwritten = h2_submit(&stream, cf, data, buf, len, err);
if(nwritten < 0) {
goto out;
}
+ DEBUGASSERT(stream);
+ }
- result = h2_progress_ingress(cf, data);
- if(result) {
- *err = result;
- nwritten = -1;
- goto out;
+ /* Call the nghttp2 send loop and flush to write ALL buffered data,
+ * headers and/or request body completely out to the network */
+ result = h2_progress_egress(cf, data);
+ /* if the stream has been closed in egress handling (nghttp2 does that
+ * when it does not like the headers, for example */
+ if(stream && stream->closed) {
+ nwritten = http2_handle_stream_close(cf, data, stream, err);
+ goto out;
+ }
+ else if(result == CURLE_AGAIN) {
+ blocked = 1;
+ }
+ else if(result) {
+ *err = result;
+ nwritten = -1;
+ goto out;
+ }
+ else if(stream && !Curl_bufq_is_empty(&stream->sendbuf)) {
+ /* although we wrote everything that nghttp2 wants to send now,
+ * there is data left in our stream send buffer unwritten. This may
+ * be due to the stream's HTTP/2 flow window being exhausted. */
+ blocked = 1;
+ }
+
+ if(stream && blocked) {
+ /* Unable to send all data, due to connection blocked or H2 window
+ * exhaustion. Data is left in our stream buffer, or nghttp2's internal
+ * frame buffer or our network out buffer. */
+ size_t rwin = nghttp2_session_get_stream_remote_window_size(ctx->h2,
+ stream->id);
+ if(rwin == 0) {
+ /* H2 flow window exhaustion. We need to HOLD upload until we get
+ * a WINDOW_UPDATE from the server. */
+ data->req.keepon |= KEEP_SEND_HOLD;
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] holding send as remote flow "
+ "window is exhausted", stream->id));
+ }
+
+ /* Whatever the cause, we need to return CURL_EAGAIN for this call.
+ * We have unwritten state that needs us being invoked again and EAGAIN
+ * is the only way to ensure that. */
+ stream->upload_blocked_len = nwritten;
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] cf_send(len=%zu) BLOCK: win %u/%zu "
+ "blocked_len=%zu",
+ stream->id, len,
+ nghttp2_session_get_remote_window_size(ctx->h2), rwin,
+ nwritten));
+ *err = CURLE_AGAIN;
+ nwritten = -1;
+ goto out;
+ }
+ else if(should_close_session(ctx)) {
+ /* nghttp2 thinks this session is done. If the stream has not been
+ * closed, this is an error state for out transfer */
+ if(stream->closed) {
+ nwritten = http2_handle_stream_close(cf, data, stream, err);
}
-
- result = h2_progress_egress(cf, data);
- if(result) {
- *err = result;
+ else {
+ DEBUGF(LOG_CF(data, cf, "send: nothing to do in this session"));
+ *err = CURLE_HTTP2;
nwritten = -1;
- goto out;
- }
-
- if(should_close_session(ctx)) {
- if(stream->closed) {
- nwritten = http2_handle_stream_close(cf, data, stream, err);
- }
- else {
- DEBUGF(LOG_CF(data, cf, "send: nothing to do in this session"));
- *err = CURLE_HTTP2;
- nwritten = -1;
- }
- goto out;
}
}
out:
if(stream) {
DEBUGF(LOG_CF(data, cf, "[h2sid=%d] cf_send(len=%zu) -> %zd, %d, "
- "buffered=%zu, upload_left=%zu, stream-window=%d, "
- "connection-window=%d",
+ "upload_left=%" CURL_FORMAT_CURL_OFF_T ", "
+ "h2 windows %d-%d (stream-conn), "
+ "buffers %zu-%zu (stream-conn)",
stream->id, len, nwritten, *err,
- Curl_bufq_len(&stream->sendbuf),
(ssize_t)stream->upload_left,
nghttp2_session_get_stream_remote_window_size(
ctx->h2, stream->id),
- nghttp2_session_get_remote_window_size(ctx->h2)));
- drain_stream(cf, data, stream);
+ nghttp2_session_get_remote_window_size(ctx->h2),
+ Curl_bufq_len(&stream->sendbuf),
+ Curl_bufq_len(&ctx->outbufq)));
}
else {
DEBUGF(LOG_CF(data, cf, "cf_send(len=%zu) -> %zd, %d, "
- "connection-window=%d",
+ "connection-window=%d, nw_send_buffer(%zu)",
len, nwritten, *err,
- nghttp2_session_get_remote_window_size(ctx->h2)));
+ nghttp2_session_get_remote_window_size(ctx->h2),
+ Curl_bufq_len(&ctx->outbufq)));
}
CF_DATA_RESTORE(cf, save);
return nwritten;
@@ -2241,8 +2320,7 @@ static CURLcode http2_data_pause(struct Curl_cfilter *cf,
DEBUGASSERT(data);
if(ctx && ctx->h2 && stream) {
- uint32_t window = !pause * H2_STREAM_WINDOW_SIZE;
- CURLcode result;
+ uint32_t window = pause? 0 : stream->local_window_size;
int rv = nghttp2_session_set_local_window_size(ctx->h2,
NGHTTP2_FLAG_NONE,
@@ -2257,10 +2335,8 @@ static CURLcode http2_data_pause(struct Curl_cfilter *cf,
if(!pause)
drain_stream(cf, data, stream);
- /* make sure the window update gets sent */
- result = h2_progress_egress(cf, data);
- if(result)
- return result;
+ /* attempt to send the window update */
+ (void)h2_progress_egress(cf, data);
if(!pause) {
/* Unpausing a h2 transfer, requires it to be run again. The server
@@ -2510,7 +2586,7 @@ CURLcode Curl_http2_switch(struct Curl_easy *data,
CURLcode result;
DEBUGASSERT(!Curl_conn_is_http2(data, conn, sockindex));
- DEBUGF(infof(data, DMSGI(data, sockindex, "switching to HTTP/2")));
+ DEBUGF(infof(data, "switching to HTTP/2"));
result = http2_cfilter_add(&cf, data, conn, sockindex);
if(result)
@@ -2569,7 +2645,7 @@ CURLcode Curl_http2_upgrade(struct Curl_easy *data,
CURLcode result;
DEBUGASSERT(!Curl_conn_is_http2(data, conn, sockindex));
- DEBUGF(infof(data, DMSGI(data, sockindex, "upgrading to HTTP/2")));
+ DEBUGF(infof(data, "upgrading to HTTP/2"));
DEBUGASSERT(data->req.upgr101 == UPGR101_RECEIVED);
result = http2_cfilter_add(&cf, data, conn, sockindex);
diff --git a/Utilities/cmcurl/lib/http_proxy.c b/Utilities/cmcurl/lib/http_proxy.c
index add376b..4fd998a 100644
--- a/Utilities/cmcurl/lib/http_proxy.c
+++ b/Utilities/cmcurl/lib/http_proxy.c
@@ -71,7 +71,7 @@ static CURLcode http_proxy_cf_connect(struct Curl_cfilter *cf,
DEBUGF(LOG_CF(data, cf, "connect"));
connect_sub:
- result = cf->next->cft->connect(cf->next, data, blocking, done);
+ result = cf->next->cft->do_connect(cf->next, data, blocking, done);
if(result || !*done)
return result;
@@ -181,7 +181,7 @@ static void http_proxy_cf_close(struct Curl_cfilter *cf,
ctx->cf_protocol = NULL;
}
if(cf->next)
- cf->next->cft->close(cf->next, data);
+ cf->next->cft->do_close(cf->next, data);
}
diff --git a/Utilities/cmcurl/lib/imap.c b/Utilities/cmcurl/lib/imap.c
index ed197c9..045fe24 100644
--- a/Utilities/cmcurl/lib/imap.c
+++ b/Utilities/cmcurl/lib/imap.c
@@ -385,11 +385,11 @@ static CURLcode imap_get_message(struct Curl_easy *data, struct bufref *out)
/***********************************************************************
*
- * state()
+ * imap_state()
*
* This is the ONLY way to change IMAP state!
*/
-static void state(struct Curl_easy *data, imapstate newstate)
+static void imap_state(struct Curl_easy *data, imapstate newstate)
{
struct imap_conn *imapc = &data->conn->proto.imapc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
@@ -441,7 +441,7 @@ static CURLcode imap_perform_capability(struct Curl_easy *data,
result = imap_sendf(data, "CAPABILITY");
if(!result)
- state(data, IMAP_CAPABILITY);
+ imap_state(data, IMAP_CAPABILITY);
return result;
}
@@ -458,7 +458,7 @@ static CURLcode imap_perform_starttls(struct Curl_easy *data)
CURLcode result = imap_sendf(data, "STARTTLS");
if(!result)
- state(data, IMAP_STARTTLS);
+ imap_state(data, IMAP_STARTTLS);
return result;
}
@@ -487,7 +487,7 @@ static CURLcode imap_perform_upgrade_tls(struct Curl_easy *data,
if(!result) {
imapc->ssldone = ssldone;
if(imapc->state != IMAP_UPGRADETLS)
- state(data, IMAP_UPGRADETLS);
+ imap_state(data, IMAP_UPGRADETLS);
if(imapc->ssldone) {
imap_to_imaps(conn);
@@ -514,7 +514,7 @@ static CURLcode imap_perform_login(struct Curl_easy *data,
/* Check we have a username and password to authenticate with and end the
connect phase if we don't */
if(!data->state.aptr.user) {
- state(data, IMAP_STOP);
+ imap_state(data, IMAP_STOP);
return result;
}
@@ -531,7 +531,7 @@ static CURLcode imap_perform_login(struct Curl_easy *data,
free(passwd);
if(!result)
- state(data, IMAP_LOGIN);
+ imap_state(data, IMAP_LOGIN);
return result;
}
@@ -615,7 +615,7 @@ static CURLcode imap_perform_authentication(struct Curl_easy *data,
with and end the connect phase if we don't */
if(imapc->preauth ||
!Curl_sasl_can_authenticate(&imapc->sasl, data)) {
- state(data, IMAP_STOP);
+ imap_state(data, IMAP_STOP);
return result;
}
@@ -624,7 +624,7 @@ static CURLcode imap_perform_authentication(struct Curl_easy *data,
if(!result) {
if(progress == SASL_INPROGRESS)
- state(data, IMAP_AUTHENTICATE);
+ imap_state(data, IMAP_AUTHENTICATE);
else if(!imapc->login_disabled && (imapc->preftype & IMAP_TYPE_CLEARTEXT))
/* Perform clear text authentication */
result = imap_perform_login(data, conn);
@@ -667,7 +667,7 @@ static CURLcode imap_perform_list(struct Curl_easy *data)
}
if(!result)
- state(data, IMAP_LIST);
+ imap_state(data, IMAP_LIST);
return result;
}
@@ -707,7 +707,7 @@ static CURLcode imap_perform_select(struct Curl_easy *data)
free(mailbox);
if(!result)
- state(data, IMAP_SELECT);
+ imap_state(data, IMAP_SELECT);
return result;
}
@@ -749,7 +749,7 @@ static CURLcode imap_perform_fetch(struct Curl_easy *data)
return CURLE_URL_MALFORMAT;
}
if(!result)
- state(data, IMAP_FETCH);
+ imap_state(data, IMAP_FETCH);
return result;
}
@@ -820,7 +820,7 @@ static CURLcode imap_perform_append(struct Curl_easy *data)
free(mailbox);
if(!result)
- state(data, IMAP_APPEND);
+ imap_state(data, IMAP_APPEND);
return result;
}
@@ -846,7 +846,7 @@ static CURLcode imap_perform_search(struct Curl_easy *data)
result = imap_sendf(data, "SEARCH %s", imap->query);
if(!result)
- state(data, IMAP_SEARCH);
+ imap_state(data, IMAP_SEARCH);
return result;
}
@@ -863,7 +863,7 @@ static CURLcode imap_perform_logout(struct Curl_easy *data)
CURLcode result = imap_sendf(data, "LOGOUT");
if(!result)
- state(data, IMAP_LOGOUT);
+ imap_state(data, IMAP_LOGOUT);
return result;
}
@@ -1017,7 +1017,7 @@ static CURLcode imap_state_auth_resp(struct Curl_easy *data,
if(!result)
switch(progress) {
case SASL_DONE:
- state(data, IMAP_STOP); /* Authenticated */
+ imap_state(data, IMAP_STOP); /* Authenticated */
break;
case SASL_IDLE: /* No mechanism left after cancellation */
if((!imapc->login_disabled) && (imapc->preftype & IMAP_TYPE_CLEARTEXT))
@@ -1049,7 +1049,7 @@ static CURLcode imap_state_login_resp(struct Curl_easy *data,
}
else
/* End of connect phase */
- state(data, IMAP_STOP);
+ imap_state(data, IMAP_STOP);
return result;
}
@@ -1075,7 +1075,7 @@ static CURLcode imap_state_listsearch_resp(struct Curl_easy *data,
result = CURLE_QUOTE_ERROR;
else
/* End of DO phase */
- state(data, IMAP_STOP);
+ imap_state(data, IMAP_STOP);
return result;
}
@@ -1143,7 +1143,7 @@ static CURLcode imap_state_fetch_resp(struct Curl_easy *data,
if(imapcode != '*') {
Curl_pgrsSetDownloadSize(data, -1);
- state(data, IMAP_STOP);
+ imap_state(data, IMAP_STOP);
return CURLE_REMOTE_FILE_NOT_FOUND;
}
@@ -1178,7 +1178,7 @@ static CURLcode imap_state_fetch_resp(struct Curl_easy *data,
if(!chunk) {
/* no size, we're done with the data */
- state(data, IMAP_STOP);
+ imap_state(data, IMAP_STOP);
return CURLE_OK;
}
result = Curl_client_write(data, CLIENTWRITE_BODY, pp->cache, chunk);
@@ -1224,7 +1224,7 @@ static CURLcode imap_state_fetch_resp(struct Curl_easy *data,
}
/* End of DO phase */
- state(data, IMAP_STOP);
+ imap_state(data, IMAP_STOP);
return result;
}
@@ -1242,7 +1242,7 @@ static CURLcode imap_state_fetch_final_resp(struct Curl_easy *data,
result = CURLE_WEIRD_SERVER_REPLY;
else
/* End of DONE phase */
- state(data, IMAP_STOP);
+ imap_state(data, IMAP_STOP);
return result;
}
@@ -1265,7 +1265,7 @@ static CURLcode imap_state_append_resp(struct Curl_easy *data, int imapcode,
Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
/* End of DO phase */
- state(data, IMAP_STOP);
+ imap_state(data, IMAP_STOP);
}
return result;
@@ -1284,7 +1284,7 @@ static CURLcode imap_state_append_final_resp(struct Curl_easy *data,
result = CURLE_UPLOAD_FAILED;
else
/* End of DONE phase */
- state(data, IMAP_STOP);
+ imap_state(data, IMAP_STOP);
return result;
}
@@ -1372,7 +1372,7 @@ static CURLcode imap_statemachine(struct Curl_easy *data,
/* fallthrough, just stop! */
default:
/* internal error */
- state(data, IMAP_STOP);
+ imap_state(data, IMAP_STOP);
break;
}
} while(!result && imapc->state != IMAP_STOP && Curl_pp_moredata(pp));
@@ -1475,7 +1475,7 @@ static CURLcode imap_connect(struct Curl_easy *data, bool *done)
return result;
/* Start off waiting for the server greeting response */
- state(data, IMAP_SERVERGREET);
+ imap_state(data, IMAP_SERVERGREET);
/* Start off with an response id of '*' */
strcpy(imapc->resptag, "*");
@@ -1516,12 +1516,12 @@ static CURLcode imap_done(struct Curl_easy *data, CURLcode status,
/* Handle responses after FETCH or APPEND transfer has finished */
if(!data->state.upload && data->set.mimepost.kind == MIMEKIND_NONE)
- state(data, IMAP_FETCH_FINAL);
+ imap_state(data, IMAP_FETCH_FINAL);
else {
/* End the APPEND command first by sending an empty line */
result = Curl_pp_sendf(data, &conn->proto.imapc.pp, "%s", "");
if(!result)
- state(data, IMAP_APPEND_FINAL);
+ imap_state(data, IMAP_APPEND_FINAL);
}
/* Run the state-machine */
@@ -1777,7 +1777,7 @@ static CURLcode imap_sendf(struct Curl_easy *data, const char *fmt, ...)
/* Calculate the tag based on the connection ID and command ID */
msnprintf(imapc->resptag, sizeof(imapc->resptag), "%c%03d",
- 'A' + curlx_sltosi(data->conn->connection_id % 26),
+ 'A' + curlx_sltosi((long)(data->conn->connection_id % 26)),
++imapc->cmdid);
/* start with a blank buffer */
@@ -1925,6 +1925,7 @@ static CURLcode imap_parse_url_options(struct connectdata *conn)
CURLcode result = CURLE_OK;
struct imap_conn *imapc = &conn->proto.imapc;
const char *ptr = conn->options;
+ bool prefer_login = false;
while(!result && ptr && *ptr) {
const char *key = ptr;
@@ -1938,26 +1939,39 @@ static CURLcode imap_parse_url_options(struct connectdata *conn)
while(*ptr && *ptr != ';')
ptr++;
- if(strncasecompare(key, "AUTH=", 5))
+ if(strncasecompare(key, "AUTH=+LOGIN", 11)) {
+ /* User prefers plaintext LOGIN over any SASL, including SASL LOGIN */
+ prefer_login = true;
+ imapc->sasl.prefmech = SASL_AUTH_NONE;
+ }
+ else if(strncasecompare(key, "AUTH=", 5)) {
+ prefer_login = false;
result = Curl_sasl_parse_url_auth_option(&imapc->sasl,
value, ptr - value);
- else
+ }
+ else {
+ prefer_login = false;
result = CURLE_URL_MALFORMAT;
+ }
if(*ptr == ';')
ptr++;
}
- switch(imapc->sasl.prefmech) {
- case SASL_AUTH_NONE:
- imapc->preftype = IMAP_TYPE_NONE;
- break;
- case SASL_AUTH_DEFAULT:
- imapc->preftype = IMAP_TYPE_ANY;
- break;
- default:
- imapc->preftype = IMAP_TYPE_SASL;
- break;
+ if(prefer_login)
+ imapc->preftype = IMAP_TYPE_CLEARTEXT;
+ else {
+ switch(imapc->sasl.prefmech) {
+ case SASL_AUTH_NONE:
+ imapc->preftype = IMAP_TYPE_NONE;
+ break;
+ case SASL_AUTH_DEFAULT:
+ imapc->preftype = IMAP_TYPE_ANY;
+ break;
+ default:
+ imapc->preftype = IMAP_TYPE_SASL;
+ break;
+ }
}
return result;
diff --git a/Utilities/cmcurl/lib/krb5.c b/Utilities/cmcurl/lib/krb5.c
index a71779a..c2ba815 100644
--- a/Utilities/cmcurl/lib/krb5.c
+++ b/Utilities/cmcurl/lib/krb5.c
@@ -261,7 +261,7 @@ krb5_auth(void *app_data, struct Curl_easy *data, struct connectdata *conn)
}
/* We pass NULL as |output_name_type| to avoid a leak. */
gss_display_name(&min, gssname, &output_buffer, NULL);
- infof(data, "Trying against %s", output_buffer.value);
+ infof(data, "Trying against %s", (char *)output_buffer.value);
gssresp = GSS_C_NO_BUFFER;
*context = GSS_C_NO_CONTEXT;
diff --git a/Utilities/cmcurl/lib/ldap.c b/Utilities/cmcurl/lib/ldap.c
index 4c88b0a..6b30ffb 100644
--- a/Utilities/cmcurl/lib/ldap.c
+++ b/Utilities/cmcurl/lib/ldap.c
@@ -50,6 +50,14 @@
#endif
#ifdef USE_WIN32_LDAP /* Use Windows LDAP implementation. */
+# ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable: 4201)
+# endif
+# include <subauth.h> /* for [P]UNICODE_STRING */
+# ifdef _MSC_VER
+# pragma warning(pop)
+# endif
# include <winldap.h>
# ifndef LDAP_VENDOR_NAME
# error Your Platform SDK is NOT sufficient for LDAP support! \
diff --git a/Utilities/cmcurl/lib/macos.c b/Utilities/cmcurl/lib/macos.c
new file mode 100644
index 0000000..5fe4e0b
--- /dev/null
+++ b/Utilities/cmcurl/lib/macos.c
@@ -0,0 +1,62 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#if defined(__APPLE__)
+
+#if !defined(TARGET_OS_OSX) || TARGET_OS_OSX
+
+#include <curl/curl.h>
+
+#include "macos.h"
+
+#if defined(ENABLE_IPV6) && defined(CURL_OSX_CALL_COPYPROXIES)
+#include <SystemConfiguration/SCDynamicStoreCopySpecific.h>
+#endif
+
+CURLcode Curl_macos_init(void)
+{
+#if defined(ENABLE_IPV6) && defined(CURL_OSX_CALL_COPYPROXIES)
+ {
+ /*
+ * The automagic conversion from IPv4 literals to IPv6 literals only
+ * works if the SCDynamicStoreCopyProxies system function gets called
+ * first. As Curl currently doesn't support system-wide HTTP proxies, we
+ * therefore don't use any value this function might return.
+ *
+ * This function is only available on a macOS and is not needed for
+ * IPv4-only builds, hence the conditions above.
+ */
+ CFDictionaryRef dict = SCDynamicStoreCopyProxies(NULL);
+ if(dict)
+ CFRelease(dict);
+ }
+#endif
+ return CURLE_OK;
+}
+
+#endif /* TARGET_OS_OSX */
+
+#endif /* __APPLE__ */
diff --git a/Utilities/cmcurl/lib/macos.h b/Utilities/cmcurl/lib/macos.h
new file mode 100644
index 0000000..3388acd
--- /dev/null
+++ b/Utilities/cmcurl/lib/macos.h
@@ -0,0 +1,38 @@
+#ifndef HEADER_CURL_MACOS_H
+#define HEADER_CURL_MACOS_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#if defined(__APPLE__) && (!defined(TARGET_OS_OSX) || TARGET_OS_OSX)
+
+CURLcode Curl_macos_init(void);
+
+#else
+
+#define Curl_macos_init() CURLE_OK
+
+#endif
+
+#endif /* HEADER_CURL_MACOS_H */
diff --git a/Utilities/cmcurl/lib/mime.c b/Utilities/cmcurl/lib/mime.c
index 39aac8f..0a57e1e 100644
--- a/Utilities/cmcurl/lib/mime.c
+++ b/Utilities/cmcurl/lib/mime.c
@@ -84,7 +84,7 @@ static const struct mime_encoder encoders[] = {
};
/* Base64 encoding table */
-static const char base64[] =
+static const char base64enc[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/* Quoted-printable character class table.
@@ -469,10 +469,10 @@ static size_t encoder_base64_read(char *buffer, size_t size, bool ateof,
i = st->buf[st->bufbeg++] & 0xFF;
i = (i << 8) | (st->buf[st->bufbeg++] & 0xFF);
i = (i << 8) | (st->buf[st->bufbeg++] & 0xFF);
- *ptr++ = base64[(i >> 18) & 0x3F];
- *ptr++ = base64[(i >> 12) & 0x3F];
- *ptr++ = base64[(i >> 6) & 0x3F];
- *ptr++ = base64[i & 0x3F];
+ *ptr++ = base64enc[(i >> 18) & 0x3F];
+ *ptr++ = base64enc[(i >> 12) & 0x3F];
+ *ptr++ = base64enc[(i >> 6) & 0x3F];
+ *ptr++ = base64enc[i & 0x3F];
cursize += 4;
st->pos += 4;
size -= 4;
@@ -496,10 +496,10 @@ static size_t encoder_base64_read(char *buffer, size_t size, bool ateof,
i = (st->buf[st->bufbeg + 1] & 0xFF) << 8;
i |= (st->buf[st->bufbeg] & 0xFF) << 16;
- ptr[0] = base64[(i >> 18) & 0x3F];
- ptr[1] = base64[(i >> 12) & 0x3F];
+ ptr[0] = base64enc[(i >> 18) & 0x3F];
+ ptr[1] = base64enc[(i >> 12) & 0x3F];
if(++st->bufbeg != st->bufend) {
- ptr[2] = base64[(i >> 6) & 0x3F];
+ ptr[2] = base64enc[(i >> 6) & 0x3F];
st->bufbeg++;
}
cursize += 4;
diff --git a/Utilities/cmcurl/lib/mqtt.c b/Utilities/cmcurl/lib/mqtt.c
index dbe7239..799a21a 100644
--- a/Utilities/cmcurl/lib/mqtt.c
+++ b/Utilities/cmcurl/lib/mqtt.c
@@ -636,7 +636,7 @@ MQTT_SUBACK_COMING:
/* -- switched state -- */
remlen = mq->remaining_length;
- infof(data, "Remaining length: %zd bytes", remlen);
+ infof(data, "Remaining length: %zu bytes", remlen);
if(data->set.max_filesize &&
(curl_off_t)remlen > data->set.max_filesize) {
failf(data, "Maximum file size exceeded");
diff --git a/Utilities/cmcurl/lib/multi.c b/Utilities/cmcurl/lib/multi.c
index d1d32b7..50bf15a 100644
--- a/Utilities/cmcurl/lib/multi.c
+++ b/Utilities/cmcurl/lib/multi.c
@@ -112,7 +112,7 @@ static CURLMcode multi_timeout(struct Curl_multi *multi,
static void process_pending_handles(struct Curl_multi *multi);
#ifdef DEBUGBUILD
-static const char * const statename[]={
+static const char * const multi_statename[]={
"INIT",
"PENDING",
"CONNECT",
@@ -194,15 +194,10 @@ static void mstate(struct Curl_easy *data, CURLMstate state
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
if(data->mstate >= MSTATE_PENDING &&
data->mstate < MSTATE_COMPLETED) {
- long connection_id = -5000;
-
- if(data->conn)
- connection_id = data->conn->connection_id;
-
infof(data,
- "STATE: %s => %s handle %p; line %d (connection #%ld)",
- statename[oldstate], statename[data->mstate],
- (void *)data, lineno, connection_id);
+ "STATE: %s => %s handle %p; line %d",
+ multi_statename[oldstate], multi_statename[data->mstate],
+ (void *)data, lineno);
}
#endif
@@ -464,6 +459,20 @@ struct Curl_multi *curl_multi_init(void)
CURL_DNS_HASH_SIZE);
}
+#ifdef DEBUGBUILD
+static void multi_warn_debug(struct Curl_multi *multi, struct Curl_easy *data)
+{
+ if(!multi->warned) {
+ infof(data, "!!! WARNING !!!");
+ infof(data, "This is a debug build of libcurl, "
+ "do not use in production.");
+ multi->warned = true;
+ }
+}
+#else
+#define multi_warn_debug(x,y) Curl_nop_stmt
+#endif
+
/* returns TRUE if the easy handle is supposed to be present in the main link
list */
static bool in_main_list(struct Curl_easy *data)
@@ -623,8 +632,14 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
data->set.server_response_timeout;
data->state.conn_cache->closure_handle->set.no_signal =
data->set.no_signal;
+ data->id = data->state.conn_cache->next_easy_id++;
+ if(data->state.conn_cache->next_easy_id <= 0)
+ data->state.conn_cache->next_easy_id = 0;
CONNCACHE_UNLOCK(data);
+ multi_warn_debug(multi, data);
+ infof(data, "processing: %s", data->state.url);
+
return CURLM_OK;
}
@@ -742,6 +757,7 @@ static CURLcode multi_done(struct Curl_easy *data,
but currently we have no such detail knowledge.
*/
+ data->state.recent_conn_id = conn->connection_id;
if((data->set.reuse_forbid
#if defined(USE_NTLM)
&& !(conn->http_ntlm_state == NTLMSTATE_TYPE2 ||
@@ -753,8 +769,9 @@ static CURLcode multi_done(struct Curl_easy *data,
#endif
) || conn->bits.close
|| (premature && !Curl_conn_is_multiplex(conn, FIRSTSOCKET))) {
- DEBUGF(infof(data, "multi_done, not re-using connection=%ld, forbid=%d"
- ", close=%d, premature=%d, conn_multiplex=%d",
+ DEBUGF(infof(data, "multi_done, not re-using connection=%"
+ CURL_FORMAT_CURL_OFF_T ", forbid=%d"
+ ", close=%d, premature=%d, conn_multiplex=%d",
conn->connection_id,
data->set.reuse_forbid, conn->bits.close, premature,
Curl_conn_is_multiplex(conn, FIRSTSOCKET)));
@@ -774,15 +791,16 @@ static CURLcode multi_done(struct Curl_easy *data,
conn->bits.conn_to_host ? conn->conn_to_host.dispname :
conn->host.dispname;
/* create string before returning the connection */
- long connection_id = conn->connection_id;
+ curl_off_t connection_id = conn->connection_id;
msnprintf(buffer, sizeof(buffer),
- "Connection #%ld to host %s left intact",
+ "Connection #%" CURL_FORMAT_CURL_OFF_T " to host %s left intact",
connection_id, host);
/* the connection is no longer in use by this transfer */
CONNCACHE_UNLOCK(data);
if(Curl_conncache_return_conn(data, conn)) {
/* remember the most recently used connection */
data->state.lastconnect_id = connection_id;
+ data->state.recent_conn_id = connection_id;
infof(data, "%s", buffer);
}
else
@@ -1895,14 +1913,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
multistate(data, MSTATE_COMPLETED);
}
-#ifdef DEBUGBUILD
- if(!multi->warned) {
- infof(data, "!!! WARNING !!!");
- infof(data, "This is a debug build of libcurl, "
- "do not use in production.");
- multi->warned = true;
- }
-#endif
+ multi_warn_debug(multi, data);
do {
/* A "stream" here is a logical stream if the protocol can handle that
@@ -3690,7 +3701,7 @@ void Curl_expire_clear(struct Curl_easy *data)
}
#ifdef DEBUGBUILD
- infof(data, "Expire cleared (transfer %p)", data);
+ infof(data, "Expire cleared");
#endif
nowp->tv_sec = 0;
nowp->tv_usec = 0;
@@ -3798,7 +3809,7 @@ void Curl_multi_dump(struct Curl_multi *multi)
/* only display handles that are not completed */
fprintf(stderr, "handle %p, state %s, %d sockets\n",
(void *)data,
- statename[data->mstate], data->numsocks);
+ multi_statename[data->mstate], data->numsocks);
for(i = 0; i < data->numsocks; i++) {
curl_socket_t s = data->sockets[i];
struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
diff --git a/Utilities/cmcurl/lib/pop3.c b/Utilities/cmcurl/lib/pop3.c
index 0de34cc..ddb98bf 100644
--- a/Utilities/cmcurl/lib/pop3.c
+++ b/Utilities/cmcurl/lib/pop3.c
@@ -282,11 +282,11 @@ static CURLcode pop3_get_message(struct Curl_easy *data, struct bufref *out)
/***********************************************************************
*
- * state()
+ * pop3_state()
*
* This is the ONLY way to change POP3 state!
*/
-static void state(struct Curl_easy *data, pop3state newstate)
+static void pop3_state(struct Curl_easy *data, pop3state newstate)
{
struct pop3_conn *pop3c = &data->conn->proto.pop3c;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
@@ -335,7 +335,7 @@ static CURLcode pop3_perform_capa(struct Curl_easy *data,
result = Curl_pp_sendf(data, &pop3c->pp, "%s", "CAPA");
if(!result)
- state(data, POP3_CAPA);
+ pop3_state(data, POP3_CAPA);
return result;
}
@@ -353,7 +353,7 @@ static CURLcode pop3_perform_starttls(struct Curl_easy *data,
CURLcode result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "%s", "STLS");
if(!result)
- state(data, POP3_STARTTLS);
+ pop3_state(data, POP3_STARTTLS);
return result;
}
@@ -383,7 +383,7 @@ static CURLcode pop3_perform_upgrade_tls(struct Curl_easy *data,
if(!result) {
pop3c->ssldone = ssldone;
if(pop3c->state != POP3_UPGRADETLS)
- state(data, POP3_UPGRADETLS);
+ pop3_state(data, POP3_UPGRADETLS);
if(pop3c->ssldone) {
pop3_to_pop3s(conn);
@@ -408,7 +408,7 @@ static CURLcode pop3_perform_user(struct Curl_easy *data,
/* Check we have a username and password to authenticate with and end the
connect phase if we don't */
if(!data->state.aptr.user) {
- state(data, POP3_STOP);
+ pop3_state(data, POP3_STOP);
return result;
}
@@ -417,7 +417,7 @@ static CURLcode pop3_perform_user(struct Curl_easy *data,
result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "USER %s",
conn->user ? conn->user : "");
if(!result)
- state(data, POP3_USER);
+ pop3_state(data, POP3_USER);
return result;
}
@@ -442,7 +442,7 @@ static CURLcode pop3_perform_apop(struct Curl_easy *data,
/* Check we have a username and password to authenticate with and end the
connect phase if we don't */
if(!data->state.aptr.user) {
- state(data, POP3_STOP);
+ pop3_state(data, POP3_STOP);
return result;
}
@@ -468,7 +468,7 @@ static CURLcode pop3_perform_apop(struct Curl_easy *data,
result = Curl_pp_sendf(data, &pop3c->pp, "APOP %s %s", conn->user, secret);
if(!result)
- state(data, POP3_APOP);
+ pop3_state(data, POP3_APOP);
return result;
}
@@ -552,7 +552,7 @@ static CURLcode pop3_perform_authentication(struct Curl_easy *data,
/* Check we have enough data to authenticate with and end the
connect phase if we don't */
if(!Curl_sasl_can_authenticate(&pop3c->sasl, data)) {
- state(data, POP3_STOP);
+ pop3_state(data, POP3_STOP);
return result;
}
@@ -562,7 +562,7 @@ static CURLcode pop3_perform_authentication(struct Curl_easy *data,
if(!result)
if(progress == SASL_INPROGRESS)
- state(data, POP3_AUTH);
+ pop3_state(data, POP3_AUTH);
}
if(!result && progress == SASL_IDLE) {
@@ -620,7 +620,7 @@ static CURLcode pop3_perform_command(struct Curl_easy *data)
pop3->custom : command));
if(!result)
- state(data, POP3_COMMAND);
+ pop3_state(data, POP3_COMMAND);
return result;
}
@@ -638,7 +638,7 @@ static CURLcode pop3_perform_quit(struct Curl_easy *data,
CURLcode result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "%s", "QUIT");
if(!result)
- state(data, POP3_QUIT);
+ pop3_state(data, POP3_QUIT);
return result;
}
@@ -831,7 +831,7 @@ static CURLcode pop3_state_auth_resp(struct Curl_easy *data,
if(!result)
switch(progress) {
case SASL_DONE:
- state(data, POP3_STOP); /* Authenticated */
+ pop3_state(data, POP3_STOP); /* Authenticated */
break;
case SASL_IDLE: /* No mechanism left after cancellation */
#ifndef CURL_DISABLE_CRYPTO_AUTH
@@ -869,7 +869,7 @@ static CURLcode pop3_state_apop_resp(struct Curl_easy *data, int pop3code,
}
else
/* End of connect phase */
- state(data, POP3_STOP);
+ pop3_state(data, POP3_STOP);
return result;
}
@@ -892,7 +892,7 @@ static CURLcode pop3_state_user_resp(struct Curl_easy *data, int pop3code,
result = Curl_pp_sendf(data, &conn->proto.pop3c.pp, "PASS %s",
conn->passwd ? conn->passwd : "");
if(!result)
- state(data, POP3_PASS);
+ pop3_state(data, POP3_PASS);
return result;
}
@@ -910,7 +910,7 @@ static CURLcode pop3_state_pass_resp(struct Curl_easy *data, int pop3code,
}
else
/* End of connect phase */
- state(data, POP3_STOP);
+ pop3_state(data, POP3_STOP);
return result;
}
@@ -929,7 +929,7 @@ static CURLcode pop3_state_command_resp(struct Curl_easy *data,
(void)instate; /* no use for this yet */
if(pop3code != '+') {
- state(data, POP3_STOP);
+ pop3_state(data, POP3_STOP);
return CURLE_WEIRD_SERVER_REPLY;
}
@@ -967,7 +967,7 @@ static CURLcode pop3_state_command_resp(struct Curl_easy *data,
}
/* End of DO phase */
- state(data, POP3_STOP);
+ pop3_state(data, POP3_STOP);
return result;
}
@@ -1037,12 +1037,12 @@ static CURLcode pop3_statemachine(struct Curl_easy *data,
break;
case POP3_QUIT:
- state(data, POP3_STOP);
+ pop3_state(data, POP3_STOP);
break;
default:
/* internal error */
- state(data, POP3_STOP);
+ pop3_state(data, POP3_STOP);
break;
}
} while(!result && pop3c->state != POP3_STOP && Curl_pp_moredata(pp));
@@ -1143,7 +1143,7 @@ static CURLcode pop3_connect(struct Curl_easy *data, bool *done)
return result;
/* Start off waiting for the server greeting response */
- state(data, POP3_SERVERGREET);
+ pop3_state(data, POP3_SERVERGREET);
result = pop3_multi_statemach(data, done);
diff --git a/Utilities/cmcurl/lib/sendf.c b/Utilities/cmcurl/lib/sendf.c
index 81ee864..437fa74 100644
--- a/Utilities/cmcurl/lib/sendf.c
+++ b/Utilities/cmcurl/lib/sendf.c
@@ -419,8 +419,6 @@ CURLcode Curl_read(struct Curl_easy *data, /* transfer */
*n += nread;
result = CURLE_OK;
out:
- /* DEBUGF(infof(data, "Curl_read(handle=%p) -> %d, nread=%ld",
- data, result, nread)); */
return result;
}
diff --git a/Utilities/cmcurl/lib/setopt.c b/Utilities/cmcurl/lib/setopt.c
index 0c3b963..b05162a 100644
--- a/Utilities/cmcurl/lib/setopt.c
+++ b/Utilities/cmcurl/lib/setopt.c
@@ -1867,6 +1867,15 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
*/
data->set.haproxyprotocol = (0 != va_arg(param, long)) ? TRUE : FALSE;
break;
+ case CURLOPT_HAPROXY_CLIENT_IP:
+ /*
+ * Set the client IP to send through HAProxy PROXY protocol
+ */
+ result = Curl_setstropt(&data->set.str[STRING_HAPROXY_CLIENT_IP],
+ va_arg(param, char *));
+ /* We enable implicitly the HAProxy protocol if we use this flag. */
+ data->set.haproxyprotocol = TRUE;
+ break;
#endif
case CURLOPT_INTERFACE:
/*
@@ -2711,7 +2720,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/* Set the list of mail recipients */
data->set.mail_rcpt = va_arg(param, struct curl_slist *);
break;
- case CURLOPT_MAIL_RCPT_ALLLOWFAILS:
+ case CURLOPT_MAIL_RCPT_ALLOWFAILS:
/* allow RCPT TO command to fail for some recipients */
data->set.mail_rcpt_allowfails = (0 != va_arg(param, long)) ? TRUE : FALSE;
break;
diff --git a/Utilities/cmcurl/lib/smb.c b/Utilities/cmcurl/lib/smb.c
index d682221..bc4e883 100644
--- a/Utilities/cmcurl/lib/smb.c
+++ b/Utilities/cmcurl/lib/smb.c
@@ -27,8 +27,6 @@
#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE)
-#define BUILDING_CURL_SMB_C
-
#ifdef WIN32
#define getpid GetCurrentProcessId
#endif
@@ -50,6 +48,199 @@
#include "curl_memory.h"
#include "memdebug.h"
+/*
+ * Definitions for SMB protocol data structures
+ */
+#if defined(_MSC_VER) || defined(__ILEC400__)
+# define PACK
+# pragma pack(push)
+# pragma pack(1)
+#elif defined(__GNUC__)
+# define PACK __attribute__((packed))
+#else
+# define PACK
+#endif
+
+#define SMB_COM_CLOSE 0x04
+#define SMB_COM_READ_ANDX 0x2e
+#define SMB_COM_WRITE_ANDX 0x2f
+#define SMB_COM_TREE_DISCONNECT 0x71
+#define SMB_COM_NEGOTIATE 0x72
+#define SMB_COM_SETUP_ANDX 0x73
+#define SMB_COM_TREE_CONNECT_ANDX 0x75
+#define SMB_COM_NT_CREATE_ANDX 0xa2
+#define SMB_COM_NO_ANDX_COMMAND 0xff
+
+#define SMB_WC_CLOSE 0x03
+#define SMB_WC_READ_ANDX 0x0c
+#define SMB_WC_WRITE_ANDX 0x0e
+#define SMB_WC_SETUP_ANDX 0x0d
+#define SMB_WC_TREE_CONNECT_ANDX 0x04
+#define SMB_WC_NT_CREATE_ANDX 0x18
+
+#define SMB_FLAGS_CANONICAL_PATHNAMES 0x10
+#define SMB_FLAGS_CASELESS_PATHNAMES 0x08
+#define SMB_FLAGS2_UNICODE_STRINGS 0x8000
+#define SMB_FLAGS2_IS_LONG_NAME 0x0040
+#define SMB_FLAGS2_KNOWS_LONG_NAME 0x0001
+
+#define SMB_CAP_LARGE_FILES 0x08
+#define SMB_GENERIC_WRITE 0x40000000
+#define SMB_GENERIC_READ 0x80000000
+#define SMB_FILE_SHARE_ALL 0x07
+#define SMB_FILE_OPEN 0x01
+#define SMB_FILE_OVERWRITE_IF 0x05
+
+#define SMB_ERR_NOACCESS 0x00050001
+
+struct smb_header {
+ unsigned char nbt_type;
+ unsigned char nbt_flags;
+ unsigned short nbt_length;
+ unsigned char magic[4];
+ unsigned char command;
+ unsigned int status;
+ unsigned char flags;
+ unsigned short flags2;
+ unsigned short pid_high;
+ unsigned char signature[8];
+ unsigned short pad;
+ unsigned short tid;
+ unsigned short pid;
+ unsigned short uid;
+ unsigned short mid;
+} PACK;
+
+struct smb_negotiate_response {
+ struct smb_header h;
+ unsigned char word_count;
+ unsigned short dialect_index;
+ unsigned char security_mode;
+ unsigned short max_mpx_count;
+ unsigned short max_number_vcs;
+ unsigned int max_buffer_size;
+ unsigned int max_raw_size;
+ unsigned int session_key;
+ unsigned int capabilities;
+ unsigned int system_time_low;
+ unsigned int system_time_high;
+ unsigned short server_time_zone;
+ unsigned char encryption_key_length;
+ unsigned short byte_count;
+ char bytes[1];
+} PACK;
+
+struct andx {
+ unsigned char command;
+ unsigned char pad;
+ unsigned short offset;
+} PACK;
+
+struct smb_setup {
+ unsigned char word_count;
+ struct andx andx;
+ unsigned short max_buffer_size;
+ unsigned short max_mpx_count;
+ unsigned short vc_number;
+ unsigned int session_key;
+ unsigned short lengths[2];
+ unsigned int pad;
+ unsigned int capabilities;
+ unsigned short byte_count;
+ char bytes[1024];
+} PACK;
+
+struct smb_tree_connect {
+ unsigned char word_count;
+ struct andx andx;
+ unsigned short flags;
+ unsigned short pw_len;
+ unsigned short byte_count;
+ char bytes[1024];
+} PACK;
+
+struct smb_nt_create {
+ unsigned char word_count;
+ struct andx andx;
+ unsigned char pad;
+ unsigned short name_length;
+ unsigned int flags;
+ unsigned int root_fid;
+ unsigned int access;
+ curl_off_t allocation_size;
+ unsigned int ext_file_attributes;
+ unsigned int share_access;
+ unsigned int create_disposition;
+ unsigned int create_options;
+ unsigned int impersonation_level;
+ unsigned char security_flags;
+ unsigned short byte_count;
+ char bytes[1024];
+} PACK;
+
+struct smb_nt_create_response {
+ struct smb_header h;
+ unsigned char word_count;
+ struct andx andx;
+ unsigned char op_lock_level;
+ unsigned short fid;
+ unsigned int create_disposition;
+
+ curl_off_t create_time;
+ curl_off_t last_access_time;
+ curl_off_t last_write_time;
+ curl_off_t last_change_time;
+ unsigned int ext_file_attributes;
+ curl_off_t allocation_size;
+ curl_off_t end_of_file;
+} PACK;
+
+struct smb_read {
+ unsigned char word_count;
+ struct andx andx;
+ unsigned short fid;
+ unsigned int offset;
+ unsigned short max_bytes;
+ unsigned short min_bytes;
+ unsigned int timeout;
+ unsigned short remaining;
+ unsigned int offset_high;
+ unsigned short byte_count;
+} PACK;
+
+struct smb_write {
+ struct smb_header h;
+ unsigned char word_count;
+ struct andx andx;
+ unsigned short fid;
+ unsigned int offset;
+ unsigned int timeout;
+ unsigned short write_mode;
+ unsigned short remaining;
+ unsigned short pad;
+ unsigned short data_length;
+ unsigned short data_offset;
+ unsigned int offset_high;
+ unsigned short byte_count;
+ unsigned char pad2;
+} PACK;
+
+struct smb_close {
+ unsigned char word_count;
+ unsigned short fid;
+ unsigned int last_mtime;
+ unsigned short byte_count;
+} PACK;
+
+struct smb_tree_disconnect {
+ unsigned char word_count;
+ unsigned short byte_count;
+} PACK;
+
+#if defined(_MSC_VER) || defined(__ILEC400__)
+# pragma pack(pop)
+#endif
+
/* Local API functions */
static CURLcode smb_setup_connection(struct Curl_easy *data,
struct connectdata *conn);
diff --git a/Utilities/cmcurl/lib/smb.h b/Utilities/cmcurl/lib/smb.h
index c35f3e9..437f4a5 100644
--- a/Utilities/cmcurl/lib/smb.h
+++ b/Utilities/cmcurl/lib/smb.h
@@ -48,203 +48,6 @@ struct smb_conn {
size_t got;
};
-/*
- * Definitions for SMB protocol data structures
- */
-#ifdef BUILDING_CURL_SMB_C
-
-#if defined(_MSC_VER) || defined(__ILEC400__)
-# define PACK
-# pragma pack(push)
-# pragma pack(1)
-#elif defined(__GNUC__)
-# define PACK __attribute__((packed))
-#else
-# define PACK
-#endif
-
-#define SMB_COM_CLOSE 0x04
-#define SMB_COM_READ_ANDX 0x2e
-#define SMB_COM_WRITE_ANDX 0x2f
-#define SMB_COM_TREE_DISCONNECT 0x71
-#define SMB_COM_NEGOTIATE 0x72
-#define SMB_COM_SETUP_ANDX 0x73
-#define SMB_COM_TREE_CONNECT_ANDX 0x75
-#define SMB_COM_NT_CREATE_ANDX 0xa2
-#define SMB_COM_NO_ANDX_COMMAND 0xff
-
-#define SMB_WC_CLOSE 0x03
-#define SMB_WC_READ_ANDX 0x0c
-#define SMB_WC_WRITE_ANDX 0x0e
-#define SMB_WC_SETUP_ANDX 0x0d
-#define SMB_WC_TREE_CONNECT_ANDX 0x04
-#define SMB_WC_NT_CREATE_ANDX 0x18
-
-#define SMB_FLAGS_CANONICAL_PATHNAMES 0x10
-#define SMB_FLAGS_CASELESS_PATHNAMES 0x08
-#define SMB_FLAGS2_UNICODE_STRINGS 0x8000
-#define SMB_FLAGS2_IS_LONG_NAME 0x0040
-#define SMB_FLAGS2_KNOWS_LONG_NAME 0x0001
-
-#define SMB_CAP_LARGE_FILES 0x08
-#define SMB_GENERIC_WRITE 0x40000000
-#define SMB_GENERIC_READ 0x80000000
-#define SMB_FILE_SHARE_ALL 0x07
-#define SMB_FILE_OPEN 0x01
-#define SMB_FILE_OVERWRITE_IF 0x05
-
-#define SMB_ERR_NOACCESS 0x00050001
-
-struct smb_header {
- unsigned char nbt_type;
- unsigned char nbt_flags;
- unsigned short nbt_length;
- unsigned char magic[4];
- unsigned char command;
- unsigned int status;
- unsigned char flags;
- unsigned short flags2;
- unsigned short pid_high;
- unsigned char signature[8];
- unsigned short pad;
- unsigned short tid;
- unsigned short pid;
- unsigned short uid;
- unsigned short mid;
-} PACK;
-
-struct smb_negotiate_response {
- struct smb_header h;
- unsigned char word_count;
- unsigned short dialect_index;
- unsigned char security_mode;
- unsigned short max_mpx_count;
- unsigned short max_number_vcs;
- unsigned int max_buffer_size;
- unsigned int max_raw_size;
- unsigned int session_key;
- unsigned int capabilities;
- unsigned int system_time_low;
- unsigned int system_time_high;
- unsigned short server_time_zone;
- unsigned char encryption_key_length;
- unsigned short byte_count;
- char bytes[1];
-} PACK;
-
-struct andx {
- unsigned char command;
- unsigned char pad;
- unsigned short offset;
-} PACK;
-
-struct smb_setup {
- unsigned char word_count;
- struct andx andx;
- unsigned short max_buffer_size;
- unsigned short max_mpx_count;
- unsigned short vc_number;
- unsigned int session_key;
- unsigned short lengths[2];
- unsigned int pad;
- unsigned int capabilities;
- unsigned short byte_count;
- char bytes[1024];
-} PACK;
-
-struct smb_tree_connect {
- unsigned char word_count;
- struct andx andx;
- unsigned short flags;
- unsigned short pw_len;
- unsigned short byte_count;
- char bytes[1024];
-} PACK;
-
-struct smb_nt_create {
- unsigned char word_count;
- struct andx andx;
- unsigned char pad;
- unsigned short name_length;
- unsigned int flags;
- unsigned int root_fid;
- unsigned int access;
- curl_off_t allocation_size;
- unsigned int ext_file_attributes;
- unsigned int share_access;
- unsigned int create_disposition;
- unsigned int create_options;
- unsigned int impersonation_level;
- unsigned char security_flags;
- unsigned short byte_count;
- char bytes[1024];
-} PACK;
-
-struct smb_nt_create_response {
- struct smb_header h;
- unsigned char word_count;
- struct andx andx;
- unsigned char op_lock_level;
- unsigned short fid;
- unsigned int create_disposition;
-
- curl_off_t create_time;
- curl_off_t last_access_time;
- curl_off_t last_write_time;
- curl_off_t last_change_time;
- unsigned int ext_file_attributes;
- curl_off_t allocation_size;
- curl_off_t end_of_file;
-} PACK;
-
-struct smb_read {
- unsigned char word_count;
- struct andx andx;
- unsigned short fid;
- unsigned int offset;
- unsigned short max_bytes;
- unsigned short min_bytes;
- unsigned int timeout;
- unsigned short remaining;
- unsigned int offset_high;
- unsigned short byte_count;
-} PACK;
-
-struct smb_write {
- struct smb_header h;
- unsigned char word_count;
- struct andx andx;
- unsigned short fid;
- unsigned int offset;
- unsigned int timeout;
- unsigned short write_mode;
- unsigned short remaining;
- unsigned short pad;
- unsigned short data_length;
- unsigned short data_offset;
- unsigned int offset_high;
- unsigned short byte_count;
- unsigned char pad2;
-} PACK;
-
-struct smb_close {
- unsigned char word_count;
- unsigned short fid;
- unsigned int last_mtime;
- unsigned short byte_count;
-} PACK;
-
-struct smb_tree_disconnect {
- unsigned char word_count;
- unsigned short byte_count;
-} PACK;
-
-#if defined(_MSC_VER) || defined(__ILEC400__)
-# pragma pack(pop)
-#endif
-
-#endif /* BUILDING_CURL_SMB_C */
-
#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \
(SIZEOF_CURL_OFF_T > 4)
diff --git a/Utilities/cmcurl/lib/smtp.c b/Utilities/cmcurl/lib/smtp.c
index c182cac..afcdd10 100644
--- a/Utilities/cmcurl/lib/smtp.c
+++ b/Utilities/cmcurl/lib/smtp.c
@@ -281,11 +281,11 @@ static CURLcode smtp_get_message(struct Curl_easy *data, struct bufref *out)
/***********************************************************************
*
- * state()
+ * smtp_state()
*
* This is the ONLY way to change SMTP state!
*/
-static void state(struct Curl_easy *data, smtpstate newstate)
+static void smtp_state(struct Curl_easy *data, smtpstate newstate)
{
struct smtp_conn *smtpc = &data->conn->proto.smtpc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
@@ -338,7 +338,7 @@ static CURLcode smtp_perform_ehlo(struct Curl_easy *data)
result = Curl_pp_sendf(data, &smtpc->pp, "EHLO %s", smtpc->domain);
if(!result)
- state(data, SMTP_EHLO);
+ smtp_state(data, SMTP_EHLO);
return result;
}
@@ -362,7 +362,7 @@ static CURLcode smtp_perform_helo(struct Curl_easy *data,
result = Curl_pp_sendf(data, &smtpc->pp, "HELO %s", smtpc->domain);
if(!result)
- state(data, SMTP_HELO);
+ smtp_state(data, SMTP_HELO);
return result;
}
@@ -381,7 +381,7 @@ static CURLcode smtp_perform_starttls(struct Curl_easy *data,
"%s", "STARTTLS");
if(!result)
- state(data, SMTP_STARTTLS);
+ smtp_state(data, SMTP_STARTTLS);
return result;
}
@@ -410,7 +410,7 @@ static CURLcode smtp_perform_upgrade_tls(struct Curl_easy *data)
if(!result) {
smtpc->ssldone = ssldone;
if(smtpc->state != SMTP_UPGRADETLS)
- state(data, SMTP_UPGRADETLS);
+ smtp_state(data, SMTP_UPGRADETLS);
if(smtpc->ssldone) {
smtp_to_smtps(conn);
@@ -499,7 +499,7 @@ static CURLcode smtp_perform_authentication(struct Curl_easy *data)
server supports authentication, and end the connect phase if not */
if(!smtpc->auth_supported ||
!Curl_sasl_can_authenticate(&smtpc->sasl, data)) {
- state(data, SMTP_STOP);
+ smtp_state(data, SMTP_STOP);
return result;
}
@@ -508,7 +508,7 @@ static CURLcode smtp_perform_authentication(struct Curl_easy *data)
if(!result) {
if(progress == SASL_INPROGRESS)
- state(data, SMTP_AUTH);
+ smtp_state(data, SMTP_AUTH);
else {
/* Other mechanisms not supported */
infof(data, "No known authentication mechanisms supported");
@@ -586,7 +586,7 @@ static CURLcode smtp_perform_command(struct Curl_easy *data)
smtp->custom : "HELP");
if(!result)
- state(data, SMTP_COMMAND);
+ smtp_state(data, SMTP_COMMAND);
return result;
}
@@ -771,7 +771,7 @@ static CURLcode smtp_perform_mail(struct Curl_easy *data)
free(size);
if(!result)
- state(data, SMTP_MAIL);
+ smtp_state(data, SMTP_MAIL);
return result;
}
@@ -812,7 +812,7 @@ static CURLcode smtp_perform_rcpt_to(struct Curl_easy *data)
free(address);
if(!result)
- state(data, SMTP_RCPT);
+ smtp_state(data, SMTP_RCPT);
return result;
}
@@ -830,7 +830,7 @@ static CURLcode smtp_perform_quit(struct Curl_easy *data,
CURLcode result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "%s", "QUIT");
if(!result)
- state(data, SMTP_QUIT);
+ smtp_state(data, SMTP_QUIT);
return result;
}
@@ -996,7 +996,7 @@ static CURLcode smtp_state_helo_resp(struct Curl_easy *data, int smtpcode,
}
else
/* End of connect phase */
- state(data, SMTP_STOP);
+ smtp_state(data, SMTP_STOP);
return result;
}
@@ -1017,7 +1017,7 @@ static CURLcode smtp_state_auth_resp(struct Curl_easy *data,
if(!result)
switch(progress) {
case SASL_DONE:
- state(data, SMTP_STOP); /* Authenticated */
+ smtp_state(data, SMTP_STOP); /* Authenticated */
break;
case SASL_IDLE: /* No mechanism left after cancellation */
failf(data, "Authentication cancelled");
@@ -1064,11 +1064,11 @@ static CURLcode smtp_state_command_resp(struct Curl_easy *data, int smtpcode,
}
else
/* End of DO phase */
- state(data, SMTP_STOP);
+ smtp_state(data, SMTP_STOP);
}
else
/* End of DO phase */
- state(data, SMTP_STOP);
+ smtp_state(data, SMTP_STOP);
}
}
@@ -1145,7 +1145,7 @@ static CURLcode smtp_state_rcpt_resp(struct Curl_easy *data,
result = Curl_pp_sendf(data, &conn->proto.smtpc.pp, "%s", "DATA");
if(!result)
- state(data, SMTP_DATA);
+ smtp_state(data, SMTP_DATA);
}
}
}
@@ -1172,7 +1172,7 @@ static CURLcode smtp_state_data_resp(struct Curl_easy *data, int smtpcode,
Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
/* End of DO phase */
- state(data, SMTP_STOP);
+ smtp_state(data, SMTP_STOP);
}
return result;
@@ -1192,7 +1192,7 @@ static CURLcode smtp_state_postdata_resp(struct Curl_easy *data,
result = CURLE_WEIRD_SERVER_REPLY;
/* End of DONE phase */
- state(data, SMTP_STOP);
+ smtp_state(data, SMTP_STOP);
return result;
}
@@ -1274,7 +1274,7 @@ static CURLcode smtp_statemachine(struct Curl_easy *data,
/* fallthrough, just stop! */
default:
/* internal error */
- state(data, SMTP_STOP);
+ smtp_state(data, SMTP_STOP);
break;
}
} while(!result && smtpc->state != SMTP_STOP && Curl_pp_moredata(pp));
@@ -1379,7 +1379,7 @@ static CURLcode smtp_connect(struct Curl_easy *data, bool *done)
return result;
/* Start off waiting for the server greeting response */
- state(data, SMTP_SERVERGREET);
+ smtp_state(data, SMTP_SERVERGREET);
result = smtp_multi_statemach(data, done);
@@ -1461,7 +1461,7 @@ static CURLcode smtp_done(struct Curl_easy *data, CURLcode status,
free(eob);
}
- state(data, SMTP_POSTDATA);
+ smtp_state(data, SMTP_POSTDATA);
/* Run the state-machine */
result = smtp_block_statemach(data, conn, FALSE);
diff --git a/Utilities/cmcurl/lib/socks.c b/Utilities/cmcurl/lib/socks.c
index 53d798a..c492d66 100644
--- a/Utilities/cmcurl/lib/socks.c
+++ b/Utilities/cmcurl/lib/socks.c
@@ -161,7 +161,7 @@ static void socksstate(struct socks_state *sx, struct Curl_easy *data,
enum connect_t oldstate = sx->state;
#ifdef DEBUG_AND_VERBOSE
/* synced with the state list in urldata.h */
- static const char * const statename[] = {
+ static const char * const socks_statename[] = {
"INIT",
"SOCKS_INIT",
"SOCKS_SEND",
@@ -193,7 +193,7 @@ static void socksstate(struct socks_state *sx, struct Curl_easy *data,
#ifdef DEBUG_AND_VERBOSE
infof(data,
"SXSTATE: %s => %s; line %d",
- statename[oldstate], statename[sx->state],
+ socks_statename[oldstate], socks_statename[sx->state],
lineno);
#endif
}
@@ -567,7 +567,6 @@ static CURLproxycode do_SOCKS5(struct Curl_cfilter *cf,
*/
struct connectdata *conn = cf->conn;
unsigned char *socksreq = (unsigned char *)data->state.buffer;
- char dest[256] = "unknown"; /* printable hostname:port */
int idx;
CURLcode result;
CURLproxycode presult;
@@ -820,8 +819,8 @@ CONNECT_REQ_INIT:
/* FALLTHROUGH */
CONNECT_RESOLVED:
case CONNECT_RESOLVED: {
+ char dest[MAX_IPADR_LEN] = "unknown"; /* printable address */
struct Curl_addrinfo *hp = NULL;
- size_t destlen;
if(dns)
hp = dns->addr;
if(!hp) {
@@ -831,8 +830,6 @@ CONNECT_RESOLVED:
}
Curl_printable_address(hp, dest, sizeof(dest));
- destlen = strlen(dest);
- msnprintf(dest + destlen, sizeof(dest) - destlen, ":%d", sx->remote_port);
len = 0;
socksreq[len++] = 5; /* version (SOCKS5) */
@@ -848,7 +845,8 @@ CONNECT_RESOLVED:
socksreq[len++] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[i];
}
- infof(data, "SOCKS5 connect to IPv4 %s (locally resolved)", dest);
+ infof(data, "SOCKS5 connect to %s:%d (locally resolved)", dest,
+ sx->remote_port);
}
#ifdef ENABLE_IPV6
else if(hp->ai_family == AF_INET6) {
@@ -862,7 +860,8 @@ CONNECT_RESOLVED:
((unsigned char *)&saddr_in6->sin6_addr.s6_addr)[i];
}
- infof(data, "SOCKS5 connect to IPv6 %s (locally resolved)", dest);
+ infof(data, "SOCKS5 connect to [%s]:%d (locally resolved)", dest,
+ sx->remote_port);
}
#endif
else {
@@ -1115,7 +1114,7 @@ static CURLcode socks_proxy_cf_connect(struct Curl_cfilter *cf,
return CURLE_OK;
}
- result = cf->next->cft->connect(cf->next, data, blocking, done);
+ result = cf->next->cft->do_connect(cf->next, data, blocking, done);
if(result || !*done)
return result;
@@ -1193,7 +1192,7 @@ static void socks_proxy_cf_close(struct Curl_cfilter *cf,
DEBUGASSERT(cf->next);
cf->connected = FALSE;
socks_proxy_cf_free(cf);
- cf->next->cft->close(cf->next, data);
+ cf->next->cft->do_close(cf->next, data);
}
static void socks_proxy_cf_destroy(struct Curl_cfilter *cf,
diff --git a/Utilities/cmcurl/lib/telnet.c b/Utilities/cmcurl/lib/telnet.c
index 643e43d..1d7a592 100644
--- a/Utilities/cmcurl/lib/telnet.c
+++ b/Utilities/cmcurl/lib/telnet.c
@@ -1534,7 +1534,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
}
while(keepon) {
- DEBUGF(infof(data, "telnet_do(handle=%p), poll %d fds", data, poll_cnt));
+ DEBUGF(infof(data, "telnet_do, poll %d fds", poll_cnt));
switch(Curl_poll(pfd, poll_cnt, interval_ms)) {
case -1: /* error, stop reading */
keepon = FALSE;
@@ -1558,8 +1558,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
* in a clean way? Seems to be timing related, happens more
* on slow debug build */
if(data->state.os_errno == ECONNRESET) {
- DEBUGF(infof(data, "telnet_do(handle=%p), unexpected ECONNRESET"
- " on recv", data));
+ DEBUGF(infof(data, "telnet_do, unexpected ECONNRESET on recv"));
}
break;
}
diff --git a/Utilities/cmcurl/lib/timeval.c b/Utilities/cmcurl/lib/timeval.c
index dca1c6f..2de79be 100644
--- a/Utilities/cmcurl/lib/timeval.c
+++ b/Utilities/cmcurl/lib/timeval.c
@@ -58,7 +58,8 @@ struct curltime Curl_now(void)
return now;
}
-#elif defined(HAVE_CLOCK_GETTIME_MONOTONIC)
+#elif defined(HAVE_CLOCK_GETTIME_MONOTONIC) || \
+ defined(HAVE_CLOCK_GETTIME_MONOTONIC_RAW)
struct curltime Curl_now(void)
{
@@ -87,6 +88,19 @@ struct curltime Curl_now(void)
have_clock_gettime = TRUE;
#endif
+#ifdef HAVE_CLOCK_GETTIME_MONOTONIC_RAW
+ if(
+#if defined(__APPLE__) && defined(HAVE_BUILTIN_AVAILABLE) && \
+ (HAVE_BUILTIN_AVAILABLE == 1)
+ have_clock_gettime &&
+#endif
+ (0 == clock_gettime(CLOCK_MONOTONIC_RAW, &tsnow))) {
+ cnow.tv_sec = tsnow.tv_sec;
+ cnow.tv_usec = (unsigned int)(tsnow.tv_nsec / 1000);
+ }
+ else
+#endif
+
if(
#if defined(__APPLE__) && defined(HAVE_BUILTIN_AVAILABLE) && \
(HAVE_BUILTIN_AVAILABLE == 1)
diff --git a/Utilities/cmcurl/lib/transfer.c b/Utilities/cmcurl/lib/transfer.c
index d2ff0c2..b678004 100644
--- a/Utilities/cmcurl/lib/transfer.c
+++ b/Utilities/cmcurl/lib/transfer.c
@@ -428,6 +428,8 @@ static CURLcode readwrite_data(struct Curl_easy *data,
size_t excess = 0; /* excess bytes read */
bool readmore = FALSE; /* used by RTP to signal for more data */
int maxloops = 100;
+ curl_off_t max_recv = data->set.max_recv_speed?
+ data->set.max_recv_speed : CURL_OFF_T_MAX;
char *buf = data->state.buffer;
DEBUGASSERT(buf);
@@ -472,7 +474,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
else {
/* read nothing but since we wanted nothing we consider this an OK
situation to proceed from */
- DEBUGF(infof(data, DMSG(data, "readwrite_data: we're done")));
+ DEBUGF(infof(data, "readwrite_data: we're done"));
nread = 0;
}
@@ -666,6 +668,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
}
k->bytecount += nread;
+ max_recv -= nread;
Curl_pgrsSetDownloadCounter(data, k->bytecount);
@@ -749,9 +752,9 @@ static CURLcode readwrite_data(struct Curl_easy *data,
break;
}
- } while(data_pending(data) && maxloops--);
+ } while((max_recv > 0) && data_pending(data) && maxloops--);
- if(maxloops <= 0) {
+ if(maxloops <= 0 || max_recv <= 0) {
/* we mark it as read-again-please */
data->state.dselect_bits = CURL_CSELECT_IN;
*comeback = TRUE;
@@ -768,7 +771,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
out:
if(result)
- DEBUGF(infof(data, DMSG(data, "readwrite_data() -> %d"), result));
+ DEBUGF(infof(data, "readwrite_data() -> %d", result));
return result;
}
@@ -1233,7 +1236,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
*done = (0 == (k->keepon&(KEEP_RECVBITS|KEEP_SENDBITS))) ? TRUE : FALSE;
out:
if(result)
- DEBUGF(infof(data, DMSG(data, "Curl_readwrite() -> %d"), result));
+ DEBUGF(infof(data, "Curl_readwrite() -> %d", result));
return result;
}
@@ -1551,10 +1554,11 @@ CURLcode Curl_follow(struct Curl_easy *data,
if((type != FOLLOW_RETRY) &&
(data->req.httpcode != 401) && (data->req.httpcode != 407) &&
- Curl_is_absolute_url(newurl, NULL, 0, FALSE))
+ Curl_is_absolute_url(newurl, NULL, 0, FALSE)) {
/* If this is not redirect due to a 401 or 407 response and an absolute
URL: don't allow a custom port number */
disallowport = TRUE;
+ }
DEBUGASSERT(data->state.uh);
uc = curl_url_set(data->state.uh, CURLUPART_URL, newurl,
diff --git a/Utilities/cmcurl/lib/url.c b/Utilities/cmcurl/lib/url.c
index 0fb6268..e3e7f45 100644
--- a/Utilities/cmcurl/lib/url.c
+++ b/Utilities/cmcurl/lib/url.c
@@ -659,6 +659,9 @@ CURLcode Curl_open(struct Curl_easy **curl)
/* most recent connection is not yet defined */
data->state.lastconnect_id = -1;
+ data->state.recent_conn_id = -1;
+ /* and not assigned an id yet */
+ data->id = -1;
data->progress.flags |= PGRS_HIDE;
data->state.current_speed = -1; /* init to negative == impossible */
@@ -680,7 +683,7 @@ CURLcode Curl_open(struct Curl_easy **curl)
static void conn_shutdown(struct Curl_easy *data)
{
DEBUGASSERT(data);
- infof(data, "Closing connection %ld", data->conn->connection_id);
+ infof(data, "Closing connection");
/* possible left-overs from the async name resolvers */
Curl_resolver_cancel(data);
@@ -763,7 +766,8 @@ void Curl_disconnect(struct Curl_easy *data,
/* the transfer must be detached from the connection */
DEBUGASSERT(!data->conn);
- DEBUGF(infof(data, "Curl_disconnect(conn #%ld, dead=%d)",
+ DEBUGF(infof(data, "Curl_disconnect(conn #%"
+ CURL_FORMAT_CURL_OFF_T ", dead=%d)",
conn->connection_id, dead_connection));
/*
* If this connection isn't marked to force-close, leave it open if there
@@ -937,6 +941,7 @@ static bool extract_if_dead(struct connectdata *conn,
else {
bool input_pending;
+ Curl_attach_connection(data, conn);
dead = !Curl_conn_is_alive(data, conn, &input_pending);
if(input_pending) {
/* For reuse, we want a "clean" connection state. The includes
@@ -949,10 +954,12 @@ static bool extract_if_dead(struct connectdata *conn,
*/
dead = TRUE;
}
+ Curl_detach_connection(data);
}
if(dead) {
- infof(data, "Connection %ld seems to be dead", conn->connection_id);
+ infof(data, "Connection %" CURL_FORMAT_CURL_OFF_T " seems to be dead",
+ conn->connection_id);
Curl_conncache_remove_conn(data, conn, FALSE);
return TRUE;
}
@@ -1147,8 +1154,8 @@ ConnectionExists(struct Curl_easy *data,
/* primary_ip[0] is NUL only if the resolving of the name hasn't
completed yet and until then we don't re-use this connection */
if(!check->primary_ip[0]) {
- infof(data,
- "Connection #%ld is still name resolving, can't reuse",
+ infof(data, "Connection #%" CURL_FORMAT_CURL_OFF_T " is still "
+ "name resolving, can't reuse",
check->connection_id);
continue;
}
@@ -1158,8 +1165,8 @@ ConnectionExists(struct Curl_easy *data,
if(!Curl_conn_is_connected(check, FIRSTSOCKET)) {
foundPendingCandidate = TRUE;
/* Don't pick a connection that hasn't connected yet */
- infof(data, "Connection #%ld isn't open enough, can't reuse",
- check->connection_id);
+ infof(data, "Connection #%" CURL_FORMAT_CURL_OFF_T
+ "isn't open enough, can't reuse", check->connection_id);
continue;
}
@@ -1335,8 +1342,8 @@ ConnectionExists(struct Curl_easy *data,
if(!Curl_ssl_config_matches(&needle->ssl_config,
&check->ssl_config)) {
DEBUGF(infof(data,
- "Connection #%ld has different SSL parameters, "
- "can't reuse",
+ "Connection #%" CURL_FORMAT_CURL_OFF_T
+ " has different SSL parameters, can't reuse",
check->connection_id));
continue;
}
@@ -1477,14 +1484,14 @@ void Curl_verboseconnect(struct Curl_easy *data,
struct connectdata *conn)
{
if(data->set.verbose)
- infof(data, "Connected to %s (%s) port %u (#%ld)",
+ infof(data, "Connected to %s (%s) port %u",
#ifndef CURL_DISABLE_PROXY
conn->bits.socksproxy ? conn->socks_proxy.host.dispname :
conn->bits.httpproxy ? conn->http_proxy.host.dispname :
#endif
conn->bits.conn_to_host ? conn->conn_to_host.dispname :
conn->host.dispname,
- conn->primary_ip, conn->port, conn->connection_id);
+ conn->primary_ip, conn->port);
}
#endif
@@ -1857,7 +1864,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
* User name and password set with their own options override the
* credentials possibly set in the URL.
*/
- if(!data->state.aptr.passwd) {
+ if(!data->set.str[STRING_PASSWORD]) {
uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password, 0);
if(!uc) {
char *decoded;
@@ -3678,15 +3685,14 @@ static CURLcode create_conn(struct Curl_easy *data,
*in_connect = conn;
#ifndef CURL_DISABLE_PROXY
- infof(data, "Re-using existing connection #%ld with %s %s",
- conn->connection_id,
+ infof(data, "Re-using existing connection with %s %s",
conn->bits.proxy?"proxy":"host",
conn->socks_proxy.host.name ? conn->socks_proxy.host.dispname :
conn->http_proxy.host.name ? conn->http_proxy.host.dispname :
conn->host.dispname);
#else
- infof(data, "Re-using existing connection #%ld with host %s",
- conn->connection_id, conn->host.dispname);
+ infof(data, "Re-using existing connection with host %s",
+ conn->host.dispname);
#endif
}
else {
diff --git a/Utilities/cmcurl/lib/urlapi.c b/Utilities/cmcurl/lib/urlapi.c
index a4530f9..e0c5476 100644
--- a/Utilities/cmcurl/lib/urlapi.c
+++ b/Utilities/cmcurl/lib/urlapi.c
@@ -201,7 +201,7 @@ static CURLUcode urlencode_str(struct dynbuf *o, const char *url,
size_t Curl_is_absolute_url(const char *url, char *buf, size_t buflen,
bool guess_scheme)
{
- int i;
+ int i = 0;
DEBUGASSERT(!buf || (buflen > MAX_SCHEME_LEN));
(void)buflen; /* only used in debug-builds */
if(buf)
@@ -210,17 +210,18 @@ size_t Curl_is_absolute_url(const char *url, char *buf, size_t buflen,
if(guess_scheme && STARTS_WITH_DRIVE_PREFIX(url))
return 0;
#endif
- for(i = 0; i < MAX_SCHEME_LEN; ++i) {
- char s = url[i];
- if(s && (ISALNUM(s) || (s == '+') || (s == '-') || (s == '.') )) {
- /* RFC 3986 3.1 explains:
- scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
- */
- }
- else {
- break;
+ if(ISALPHA(url[0]))
+ for(i = 1; i < MAX_SCHEME_LEN; ++i) {
+ char s = url[i];
+ if(s && (ISALNUM(s) || (s == '+') || (s == '-') || (s == '.') )) {
+ /* RFC 3986 3.1 explains:
+ scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
+ */
+ }
+ else {
+ break;
+ }
}
- }
if(i && (url[i] == ':') && ((url[i + 1] == '/') || !guess_scheme)) {
/* If this does not guess scheme, the scheme always ends with the colon so
that this also detects data: URLs etc. In guessing mode, data: could
@@ -1546,7 +1547,7 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
}
}
- url = aprintf("%s://%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+ url = aprintf("%s://%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
scheme,
u->user ? u->user : "",
u->password ? ":": "",
@@ -1557,7 +1558,6 @@ CURLUcode curl_url_get(const CURLU *u, CURLUPart what,
allochost ? allochost : u->host,
port ? ":": "",
port ? port : "",
- (u->path && (u->path[0] != '/')) ? "/": "",
u->path ? u->path : "/",
(u->query && u->query[0]) ? "?": "",
(u->query && u->query[0]) ? u->query : "",
@@ -1639,8 +1639,10 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
bool urlencode = (flags & CURLU_URLENCODE)? 1 : 0;
bool plusencode = FALSE;
bool urlskipslash = FALSE;
+ bool leadingslash = FALSE;
bool appendquery = FALSE;
bool equalsencode = FALSE;
+ size_t nalloc;
if(!u)
return CURLUE_BAD_HANDLE;
@@ -1693,6 +1695,11 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
return CURLUE_OK;
}
+ nalloc = strlen(part);
+ if(nalloc > CURL_MAX_INPUT_LENGTH)
+ /* excessive input length */
+ return CURLUE_MALFORMED_INPUT;
+
switch(what) {
case CURLUPART_SCHEME: {
size_t plen = strlen(part);
@@ -1706,13 +1713,17 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
return CURLUE_UNSUPPORTED_SCHEME;
storep = &u->scheme;
urlencode = FALSE; /* never */
- /* ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) */
- while(plen--) {
- if(ISALNUM(*s) || (*s == '+') || (*s == '-') || (*s == '.'))
- s++; /* fine */
- else
- return CURLUE_BAD_SCHEME;
+ if(ISALPHA(*s)) {
+ /* ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) */
+ while(--plen) {
+ if(ISALNUM(*s) || (*s == '+') || (*s == '-') || (*s == '.'))
+ s++; /* fine */
+ else
+ return CURLUE_BAD_SCHEME;
+ }
}
+ else
+ return CURLUE_BAD_SCHEME;
break;
}
case CURLUPART_USER:
@@ -1746,6 +1757,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
break;
case CURLUPART_PATH:
urlskipslash = TRUE;
+ leadingslash = TRUE; /* enforce */
storep = &u->path;
break;
case CURLUPART_QUERY:
@@ -1794,18 +1806,17 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
}
DEBUGASSERT(storep);
{
- const char *newp = part;
- size_t nalloc = strlen(part);
-
- if(nalloc > CURL_MAX_INPUT_LENGTH)
- /* excessive input length */
- return CURLUE_MALFORMED_INPUT;
+ const char *newp;
+ struct dynbuf enc;
+ Curl_dyn_init(&enc, nalloc * 3 + 1 + leadingslash);
+ if(leadingslash && (part[0] != '/')) {
+ CURLcode result = Curl_dyn_addn(&enc, "/", 1);
+ if(result)
+ return CURLUE_OUT_OF_MEMORY;
+ }
if(urlencode) {
const unsigned char *i;
- struct dynbuf enc;
-
- Curl_dyn_init(&enc, nalloc * 3 + 1);
for(i = (const unsigned char *)part; *i; i++) {
CURLcode result;
@@ -1833,14 +1844,13 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
return CURLUE_OUT_OF_MEMORY;
}
}
- newp = Curl_dyn_ptr(&enc);
}
else {
char *p;
- newp = strdup(part);
- if(!newp)
+ CURLcode result = Curl_dyn_add(&enc, part);
+ if(result)
return CURLUE_OUT_OF_MEMORY;
- p = (char *)newp;
+ p = Curl_dyn_ptr(&enc);
while(*p) {
/* make sure percent encoded are lower case */
if((*p == '%') && ISXDIGIT(p[1]) && ISXDIGIT(p[2]) &&
@@ -1853,6 +1863,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
p++;
}
}
+ newp = Curl_dyn_ptr(&enc);
if(appendquery) {
/* Append the 'newp' string onto the old query. Add a '&' separator if
@@ -1861,24 +1872,24 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
size_t querylen = u->query ? strlen(u->query) : 0;
bool addamperand = querylen && (u->query[querylen -1] != '&');
if(querylen) {
- struct dynbuf enc;
- Curl_dyn_init(&enc, CURL_MAX_INPUT_LENGTH);
+ struct dynbuf qbuf;
+ Curl_dyn_init(&qbuf, CURL_MAX_INPUT_LENGTH);
- if(Curl_dyn_addn(&enc, u->query, querylen)) /* add original query */
+ if(Curl_dyn_addn(&qbuf, u->query, querylen)) /* add original query */
goto nomem;
if(addamperand) {
- if(Curl_dyn_addn(&enc, "&", 1))
+ if(Curl_dyn_addn(&qbuf, "&", 1))
goto nomem;
}
- if(Curl_dyn_add(&enc, newp))
+ if(Curl_dyn_add(&qbuf, newp))
goto nomem;
- free((char *)newp);
+ Curl_dyn_free(&enc);
free(*storep);
- *storep = Curl_dyn_ptr(&enc);
+ *storep = Curl_dyn_ptr(&qbuf);
return CURLUE_OK;
nomem:
- free((char *)newp);
+ Curl_dyn_free(&enc);
return CURLUE_OUT_OF_MEMORY;
}
}
@@ -1890,7 +1901,7 @@ nomem:
}
else {
if(!n || hostname_check(u, (char *)newp, n)) {
- free((char *)newp);
+ Curl_dyn_free(&enc);
return CURLUE_BAD_HOSTNAME;
}
}
diff --git a/Utilities/cmcurl/lib/urldata.h b/Utilities/cmcurl/lib/urldata.h
index f02e665..c45913b 100644
--- a/Utilities/cmcurl/lib/urldata.h
+++ b/Utilities/cmcurl/lib/urldata.h
@@ -882,8 +882,8 @@ struct connectdata {
#define CONN_INUSE(c) ((c)->easyq.size)
/**** Fields set when inited and not modified again */
- long connection_id; /* Contains a unique number to make it easier to
- track the connections in the log output */
+ curl_off_t connection_id; /* Contains a unique number to make it easier to
+ track the connections in the log output */
/* 'dns_entry' is the particular host we use. This points to an entry in the
DNS cache and it will not get pruned while locked. It gets unlocked in
@@ -1294,7 +1294,9 @@ struct UrlState {
/* buffers to store authentication data in, as parsed from input options */
struct curltime keeps_speed; /* for the progress meter really */
- long lastconnect_id; /* The last connection, -1 if undefined */
+ curl_off_t lastconnect_id; /* The last connection, -1 if undefined */
+ curl_off_t recent_conn_id; /* The most recent connection used, might no
+ * longer exist */
struct dynbuf headerb; /* buffer to store headers in */
char *buffer; /* download buffer */
@@ -1563,6 +1565,7 @@ enum dupstring {
STRING_DNS_LOCAL_IP6,
STRING_SSL_EC_CURVES,
STRING_AWS_SIGV4, /* Parameters for V4 signature */
+ STRING_HAPROXY_CLIENT_IP, /* CURLOPT_HAPROXY_CLIENT_IP */
/* -- end of null-terminated strings -- */
@@ -1902,6 +1905,13 @@ struct Curl_easy {
/* First a simple identifier to easier detect if a user mix up this easy
handle with a multi handle. Set this to CURLEASY_MAGIC_NUMBER */
unsigned int magic;
+ /* once an easy handle is tied to a connection cache
+ a non-negative number to distinguish this transfer from
+ other using the same cache. For easier tracking
+ in log output.
+ This may wrap around after LONG_MAX to 0 again, so it
+ has no uniqueness guarantuee for very large processings. */
+ curl_off_t id;
/* first, two fields for the linked list of these */
struct Curl_easy *next;
diff --git a/Utilities/cmcurl/lib/version.c b/Utilities/cmcurl/lib/version.c
index 5800ad3..f99dd38 100644
--- a/Utilities/cmcurl/lib/version.c
+++ b/Utilities/cmcurl/lib/version.c
@@ -300,7 +300,7 @@ char *curl_version(void)
protocol line has its own #if line to make things easier on the eye.
*/
-static const char * const protocols[] = {
+static const char * const supported_protocols[] = {
#ifndef CURL_DISABLE_DICT
"dict",
#endif
@@ -535,7 +535,7 @@ static curl_version_info_data version_info = {
NULL, /* ssl_version */
0, /* ssl_version_num, this is kept at zero */
NULL, /* zlib_version */
- protocols,
+ supported_protocols,
NULL, /* c-ares version */
0, /* c-ares version numerical */
NULL, /* libidn version */
diff --git a/Utilities/cmcurl/lib/vquic/curl_msh3.c b/Utilities/cmcurl/lib/vquic/curl_msh3.c
index 1738867..02b5334 100644
--- a/Utilities/cmcurl/lib/vquic/curl_msh3.c
+++ b/Utilities/cmcurl/lib/vquic/curl_msh3.c
@@ -123,6 +123,7 @@ struct cf_msh3_ctx {
};
/* How to access `call_data` from a cf_msh3 filter */
+#undef CF_CTX_CALL_DATA
#define CF_CTX_CALL_DATA(cf) \
((struct cf_msh3_ctx *)(cf)->ctx)->call_data
@@ -172,7 +173,7 @@ static CURLcode h3_data_setup(struct Curl_cfilter *cf,
msh3_lock_initialize(&stream->recv_lock);
Curl_bufq_init2(&stream->recvbuf, H3_STREAM_CHUNK_SIZE,
H3_STREAM_RECV_CHUNKS, BUFQ_OPT_SOFT_LIMIT);
- DEBUGF(LOG_CF(data, cf, "data setup (easy %p)", (void *)data));
+ DEBUGF(LOG_CF(data, cf, "data setup"));
return CURLE_OK;
}
@@ -645,7 +646,7 @@ static ssize_t cf_msh3_send(struct Curl_cfilter *cf, struct Curl_easy *data,
}
else {
/* request is open */
- DEBUGF(LOG_CF(data, cf, "req: send %zd body bytes", len));
+ DEBUGF(LOG_CF(data, cf, "req: send %zu body bytes", len));
if(len > 0xFFFFFFFF) {
len = 0xFFFFFFFF;
}
diff --git a/Utilities/cmcurl/lib/vquic/curl_ngtcp2.c b/Utilities/cmcurl/lib/vquic/curl_ngtcp2.c
index 7627940..a430aa1 100644
--- a/Utilities/cmcurl/lib/vquic/curl_ngtcp2.c
+++ b/Utilities/cmcurl/lib/vquic/curl_ngtcp2.c
@@ -33,7 +33,7 @@
#ifdef OPENSSL_IS_BORINGSSL
#include <ngtcp2/ngtcp2_crypto_boringssl.h>
#else
-#include <ngtcp2/ngtcp2_crypto_openssl.h>
+#include <ngtcp2/ngtcp2_crypto_quictls.h>
#endif
#include "vtls/openssl.h"
#elif defined(USE_GNUTLS)
@@ -165,17 +165,19 @@ struct cf_ngtcp2_ctx {
};
/* How to access `call_data` from a cf_ngtcp2 filter */
+#undef CF_CTX_CALL_DATA
#define CF_CTX_CALL_DATA(cf) \
((struct cf_ngtcp2_ctx *)(cf)->ctx)->call_data
/**
* All about the H3 internals of a stream
*/
-struct stream_ctx {
+struct h3_stream_ctx {
int64_t id; /* HTTP/3 protocol identifier */
struct bufq sendbuf; /* h3 request body */
struct bufq recvbuf; /* h3 response body */
size_t sendbuf_len_in_flight; /* sendbuf amount "in flight" */
+ size_t upload_blocked_len; /* the amount written last and EGAINed */
size_t recv_buf_nonflow; /* buffered bytes, not counting for flow control */
uint64_t error3; /* HTTP/3 stream error code */
curl_off_t upload_left; /* number of request bytes left to upload */
@@ -186,18 +188,18 @@ struct stream_ctx {
bool send_closed; /* stream is local closed */
};
-#define H3_STREAM_CTX(d) ((struct stream_ctx *)(((d) && (d)->req.p.http)? \
- ((struct HTTP *)(d)->req.p.http)->h3_ctx \
- : NULL))
-#define H3_STREAM_LCTX(d) ((struct HTTP *)(d)->req.p.http)->h3_ctx
-#define H3_STREAM_ID(d) (H3_STREAM_CTX(d)? \
- H3_STREAM_CTX(d)->id : -2)
+#define H3_STREAM_CTX(d) ((struct h3_stream_ctx *)(((d) && (d)->req.p.http)? \
+ ((struct HTTP *)(d)->req.p.http)->h3_ctx \
+ : NULL))
+#define H3_STREAM_LCTX(d) ((struct HTTP *)(d)->req.p.http)->h3_ctx
+#define H3_STREAM_ID(d) (H3_STREAM_CTX(d)? \
+ H3_STREAM_CTX(d)->id : -2)
static CURLcode h3_data_setup(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
struct cf_ngtcp2_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = H3_STREAM_CTX(data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
if(!data || !data->req.p.http) {
failf(data, "initialization failure, transfer not http initialized");
@@ -223,13 +225,13 @@ static CURLcode h3_data_setup(struct Curl_cfilter *cf,
stream->recv_buf_nonflow = 0;
H3_STREAM_LCTX(data) = stream;
- DEBUGF(LOG_CF(data, cf, "data setup (easy %p)", (void *)data));
+ DEBUGF(LOG_CF(data, cf, "data setup"));
return CURLE_OK;
}
static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data)
{
- struct stream_ctx *stream = H3_STREAM_CTX(data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
(void)cf;
if(stream) {
@@ -246,10 +248,37 @@ static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data)
the maximum packet burst to MAX_PKT_BURST packets. */
#define MAX_PKT_BURST 10
-static CURLcode cf_process_ingress(struct Curl_cfilter *cf,
- struct Curl_easy *data);
-static CURLcode cf_flush_egress(struct Curl_cfilter *cf,
- struct Curl_easy *data);
+struct pkt_io_ctx {
+ struct Curl_cfilter *cf;
+ struct Curl_easy *data;
+ ngtcp2_tstamp ts;
+ size_t pkt_count;
+ ngtcp2_path_storage ps;
+};
+
+static ngtcp2_tstamp timestamp(void)
+{
+ struct curltime ct = Curl_now();
+ return ct.tv_sec * NGTCP2_SECONDS + ct.tv_usec * NGTCP2_MICROSECONDS;
+}
+
+static void pktx_init(struct pkt_io_ctx *pktx,
+ struct Curl_cfilter *cf,
+ struct Curl_easy *data)
+{
+ pktx->cf = cf;
+ pktx->data = data;
+ pktx->ts = timestamp();
+ pktx->pkt_count = 0;
+ ngtcp2_path_storage_zero(&pktx->ps);
+}
+
+static CURLcode cf_progress_ingress(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct pkt_io_ctx *pktx);
+static CURLcode cf_progress_egress(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct pkt_io_ctx *pktx);
static int cb_h3_acked_req_body(nghttp3_conn *conn, int64_t stream_id,
uint64_t datalen, void *user_data,
void *stream_user_data);
@@ -261,12 +290,6 @@ static ngtcp2_conn *get_conn(ngtcp2_crypto_conn_ref *conn_ref)
return ctx->qconn;
}
-static ngtcp2_tstamp timestamp(void)
-{
- struct curltime ct = Curl_now();
- return ct.tv_sec * NGTCP2_SECONDS + ct.tv_usec * NGTCP2_MICROSECONDS;
-}
-
#ifdef DEBUG_NGTCP2
static void quic_printf(void *user_data, const char *fmt, ...)
{
@@ -300,7 +323,8 @@ static void qlog_callback(void *user_data, uint32_t flags,
}
static void quic_settings(struct cf_ngtcp2_ctx *ctx,
- struct Curl_easy *data)
+ struct Curl_easy *data,
+ struct pkt_io_ctx *pktx)
{
ngtcp2_settings *s = &ctx->settings;
ngtcp2_transport_params *t = &ctx->transport_params;
@@ -314,7 +338,7 @@ static void quic_settings(struct cf_ngtcp2_ctx *ctx,
#endif
(void)data;
- s->initial_ts = timestamp();
+ s->initial_ts = pktx->ts;
s->handshake_timeout = QUIC_HANDSHAKE_TIMEOUT;
s->max_window = 100 * ctx->max_stream_window;
s->max_stream_window = ctx->max_stream_window;
@@ -327,7 +351,7 @@ static void quic_settings(struct cf_ngtcp2_ctx *ctx,
t->initial_max_streams_uni = QUIC_MAX_STREAMS;
t->max_idle_timeout = QUIC_IDLE_TIMEOUT;
if(ctx->qlogfd != -1) {
- s->qlog.write = qlog_callback;
+ s->qlog_write = qlog_callback;
}
}
@@ -383,8 +407,8 @@ static CURLcode quic_ssl_ctx(SSL_CTX **pssl_ctx,
goto out;
}
#else
- if(ngtcp2_crypto_openssl_configure_client_context(ssl_ctx) != 0) {
- failf(data, "ngtcp2_crypto_openssl_configure_client_context failed");
+ if(ngtcp2_crypto_quictls_configure_client_context(ssl_ctx) != 0) {
+ failf(data, "ngtcp2_crypto_quictls_configure_client_context failed");
goto out;
}
#endif
@@ -686,7 +710,7 @@ static void report_consumed_data(struct Curl_cfilter *cf,
struct Curl_easy *data,
size_t consumed)
{
- struct stream_ctx *stream = H3_STREAM_CTX(data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
struct cf_ngtcp2_ctx *ctx = cf->ctx;
if(!stream)
@@ -902,13 +926,13 @@ static int cb_get_new_connection_id(ngtcp2_conn *tconn, ngtcp2_cid *cid,
return 0;
}
-static int cb_recv_rx_key(ngtcp2_conn *tconn, ngtcp2_crypto_level level,
+static int cb_recv_rx_key(ngtcp2_conn *tconn, ngtcp2_encryption_level level,
void *user_data)
{
struct Curl_cfilter *cf = user_data;
(void)tconn;
- if(level != NGTCP2_CRYPTO_LEVEL_APPLICATION) {
+ if(level != NGTCP2_ENCRYPTION_LEVEL_1RTT) {
return 0;
}
@@ -962,6 +986,61 @@ static ngtcp2_callbacks ng_callbacks = {
NULL, /* early_data_rejected */
};
+/**
+ * Connection maintenance like timeouts on packet ACKs etc. are done by us, not
+ * the OS like for TCP. POLL events on the socket therefore are not
+ * sufficient.
+ * ngtcp2 tells us when it wants to be invoked again. We handle that via
+ * the `Curl_expire()` mechanisms.
+ */
+static CURLcode check_and_set_expiry(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct pkt_io_ctx *pktx)
+{
+ struct cf_ngtcp2_ctx *ctx = cf->ctx;
+ struct pkt_io_ctx local_pktx;
+ ngtcp2_tstamp expiry;
+
+ if(!pktx) {
+ pktx_init(&local_pktx, cf, data);
+ pktx = &local_pktx;
+ }
+ else {
+ pktx->ts = timestamp();
+ }
+
+ expiry = ngtcp2_conn_get_expiry(ctx->qconn);
+ if(expiry != UINT64_MAX) {
+ if(expiry <= pktx->ts) {
+ CURLcode result;
+ int rv = ngtcp2_conn_handle_expiry(ctx->qconn, pktx->ts);
+ if(rv) {
+ failf(data, "ngtcp2_conn_handle_expiry returned error: %s",
+ ngtcp2_strerror(rv));
+ ngtcp2_ccerr_set_liberr(&ctx->last_error, rv, NULL, 0);
+ return CURLE_SEND_ERROR;
+ }
+ result = cf_progress_ingress(cf, data, pktx);
+ if(result)
+ return result;
+ result = cf_progress_egress(cf, data, pktx);
+ if(result)
+ return result;
+ /* ask again, things might have changed */
+ expiry = ngtcp2_conn_get_expiry(ctx->qconn);
+ }
+
+ if(expiry > pktx->ts) {
+ ngtcp2_duration timeout = expiry - pktx->ts;
+ if(timeout % NGTCP2_MILLISECONDS) {
+ timeout += NGTCP2_MILLISECONDS;
+ }
+ Curl_expire(data, timeout / NGTCP2_MILLISECONDS, EXPIRE_QUIC);
+ }
+ }
+ return CURLE_OK;
+}
+
static int cf_ngtcp2_get_select_socks(struct Curl_cfilter *cf,
struct Curl_easy *data,
curl_socket_t *socks)
@@ -969,7 +1048,7 @@ static int cf_ngtcp2_get_select_socks(struct Curl_cfilter *cf,
struct cf_ngtcp2_ctx *ctx = cf->ctx;
struct SingleRequest *k = &data->req;
int rv = GETSOCK_BLANK;
- struct stream_ctx *stream = H3_STREAM_CTX(data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
struct cf_call_data save;
CF_DATA_SAVE(save, cf, data);
@@ -991,15 +1070,15 @@ static int cf_ngtcp2_get_select_socks(struct Curl_cfilter *cf,
return rv;
}
-static void drain_stream(struct Curl_cfilter *cf,
- struct Curl_easy *data)
+static void h3_drain_stream(struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
- struct stream_ctx *stream = H3_STREAM_CTX(data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
unsigned char bits;
(void)cf;
bits = CURL_CSELECT_IN;
- if(stream && !stream->send_closed && stream->upload_left)
+ if(stream && stream->upload_left && !stream->send_closed)
bits |= CURL_CSELECT_OUT;
if(data->state.dselect_bits != bits) {
data->state.dselect_bits = bits;
@@ -1013,7 +1092,7 @@ static int cb_h3_stream_close(nghttp3_conn *conn, int64_t stream_id,
{
struct Curl_cfilter *cf = user_data;
struct Curl_easy *data = stream_user_data;
- struct stream_ctx *stream = H3_STREAM_CTX(data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
(void)conn;
(void)stream_id;
(void)app_error_code;
@@ -1031,7 +1110,7 @@ static int cb_h3_stream_close(nghttp3_conn *conn, int64_t stream_id,
stream->reset = TRUE;
stream->send_closed = TRUE;
}
- drain_stream(cf, data);
+ h3_drain_stream(cf, data);
return 0;
}
@@ -1045,7 +1124,7 @@ static CURLcode write_resp_raw(struct Curl_cfilter *cf,
const void *mem, size_t memlen,
bool flow)
{
- struct stream_ctx *stream = H3_STREAM_CTX(data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
CURLcode result = CURLE_OK;
ssize_t nwritten;
@@ -1085,7 +1164,7 @@ static int cb_h3_recv_data(nghttp3_conn *conn, int64_t stream3_id,
(void)stream3_id;
result = write_resp_raw(cf, data, buf, buflen, TRUE);
- drain_stream(cf, data);
+ h3_drain_stream(cf, data);
return result? -1 : 0;
}
@@ -1110,7 +1189,7 @@ static int cb_h3_end_headers(nghttp3_conn *conn, int64_t stream_id,
{
struct Curl_cfilter *cf = user_data;
struct Curl_easy *data = stream_user_data;
- struct stream_ctx *stream = H3_STREAM_CTX(data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
CURLcode result = CURLE_OK;
(void)conn;
(void)stream_id;
@@ -1130,7 +1209,7 @@ static int cb_h3_end_headers(nghttp3_conn *conn, int64_t stream_id,
if(stream->status_code / 100 != 1) {
stream->resp_hds_complete = TRUE;
}
- drain_stream(cf, data);
+ h3_drain_stream(cf, data);
return 0;
}
@@ -1143,7 +1222,7 @@ static int cb_h3_recv_header(nghttp3_conn *conn, int64_t stream_id,
nghttp3_vec h3name = nghttp3_rcbuf_get_buf(name);
nghttp3_vec h3val = nghttp3_rcbuf_get_buf(value);
struct Curl_easy *data = stream_user_data;
- struct stream_ctx *stream = H3_STREAM_CTX(data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
CURLcode result = CURLE_OK;
(void)conn;
(void)stream_id;
@@ -1207,7 +1286,8 @@ static int cb_h3_stop_sending(nghttp3_conn *conn, int64_t stream_id,
(void)conn;
(void)stream_user_data;
- rv = ngtcp2_conn_shutdown_stream_read(ctx->qconn, stream_id, app_error_code);
+ rv = ngtcp2_conn_shutdown_stream_read(ctx->qconn, 0, stream_id,
+ app_error_code);
if(rv && rv != NGTCP2_ERR_STREAM_NOT_FOUND) {
return NGTCP2_ERR_CALLBACK_FAILURE;
}
@@ -1225,7 +1305,7 @@ static int cb_h3_reset_stream(nghttp3_conn *conn, int64_t stream_id,
(void)conn;
(void)data;
- rv = ngtcp2_conn_shutdown_stream_write(ctx->qconn, stream_id,
+ rv = ngtcp2_conn_shutdown_stream_write(ctx->qconn, 0, stream_id,
app_error_code);
DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] reset -> %d", stream_id, rv));
if(rv && rv != NGTCP2_ERR_STREAM_NOT_FOUND) {
@@ -1249,7 +1329,8 @@ static nghttp3_callbacks ngh3_callbacks = {
cb_h3_stop_sending,
NULL, /* end_stream */
cb_h3_reset_stream,
- NULL /* shutdown */
+ NULL, /* shutdown */
+ NULL /* recv_settings */
};
static int init_ngh3_conn(struct Curl_cfilter *cf)
@@ -1314,7 +1395,7 @@ fail:
static ssize_t recv_closed_stream(struct Curl_cfilter *cf,
struct Curl_easy *data,
- struct stream_ctx *stream,
+ struct h3_stream_ctx *stream,
CURLcode *err)
{
ssize_t nread = -1;
@@ -1364,9 +1445,10 @@ static ssize_t cf_ngtcp2_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
char *buf, size_t len, CURLcode *err)
{
struct cf_ngtcp2_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = H3_STREAM_CTX(data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
ssize_t nread = -1;
struct cf_call_data save;
+ struct pkt_io_ctx pktx;
(void)ctx;
@@ -1377,6 +1459,8 @@ static ssize_t cf_ngtcp2_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
DEBUGASSERT(ctx->h3conn);
*err = CURLE_OK;
+ pktx_init(&pktx, cf, data);
+
if(!stream) {
*err = CURLE_RECV_ERROR;
goto out;
@@ -1392,7 +1476,7 @@ static ssize_t cf_ngtcp2_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
report_consumed_data(cf, data, nread);
}
- if(cf_process_ingress(cf, data)) {
+ if(cf_progress_ingress(cf, data, &pktx)) {
*err = CURLE_RECV_ERROR;
nread = -1;
goto out;
@@ -1410,7 +1494,7 @@ static ssize_t cf_ngtcp2_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
}
if(nread > 0) {
- drain_stream(cf, data);
+ h3_drain_stream(cf, data);
}
else {
if(stream->closed) {
@@ -1422,10 +1506,17 @@ static ssize_t cf_ngtcp2_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
}
out:
- if(cf_flush_egress(cf, data)) {
+ if(cf_progress_egress(cf, data, &pktx)) {
*err = CURLE_SEND_ERROR;
nread = -1;
}
+ else {
+ CURLcode result2 = check_and_set_expiry(cf, data, &pktx);
+ if(result2) {
+ *err = result2;
+ nread = -1;
+ }
+ }
DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] cf_recv(len=%zu) -> %zd, %d",
stream? stream->id : -1, len, nread, *err));
CF_DATA_RESTORE(cf, save);
@@ -1438,7 +1529,7 @@ static int cb_h3_acked_req_body(nghttp3_conn *conn, int64_t stream_id,
{
struct Curl_cfilter *cf = user_data;
struct Curl_easy *data = stream_user_data;
- struct stream_ctx *stream = H3_STREAM_CTX(data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
size_t skiplen;
(void)cf;
@@ -1454,10 +1545,8 @@ static int cb_h3_acked_req_body(nghttp3_conn *conn, int64_t stream_id,
Curl_bufq_skip(&stream->sendbuf, skiplen);
stream->sendbuf_len_in_flight -= skiplen;
- /* `sendbuf` *might* now have more room. If so, resume this
- * possibly paused stream. And also tell our transfer engine that
- * it may continue KEEP_SEND if told to PAUSE. */
- if(!Curl_bufq_is_full(&stream->sendbuf)) {
+ /* Everything ACKed, we resume upload processing */
+ if(!stream->sendbuf_len_in_flight) {
int rv = nghttp3_conn_resume_stream(conn, stream_id);
if(rv) {
return NGTCP2_ERR_CALLBACK_FAILURE;
@@ -1465,7 +1554,7 @@ static int cb_h3_acked_req_body(nghttp3_conn *conn, int64_t stream_id,
if((data->req.keepon & KEEP_SEND_HOLD) &&
(data->req.keepon & KEEP_SEND)) {
data->req.keepon &= ~KEEP_SEND_HOLD;
- drain_stream(cf, data);
+ h3_drain_stream(cf, data);
DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] unpausing acks",
stream_id));
}
@@ -1481,7 +1570,7 @@ cb_h3_read_req_body(nghttp3_conn *conn, int64_t stream_id,
{
struct Curl_cfilter *cf = user_data;
struct Curl_easy *data = stream_user_data;
- struct stream_ctx *stream = H3_STREAM_CTX(data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
ssize_t nwritten = 0;
size_t nvecs = 0;
(void)cf;
@@ -1530,8 +1619,10 @@ cb_h3_read_req_body(nghttp3_conn *conn, int64_t stream_id,
}
DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] read req body -> "
- "%d vecs%s with %zu (buffered=%zu, left=%zd)", stream->id,
- (int)nvecs, *pflags == NGHTTP3_DATA_FLAG_EOF?" EOF":"",
+ "%d vecs%s with %zu (buffered=%zu, left=%"
+ CURL_FORMAT_CURL_OFF_T ")",
+ stream->id, (int)nvecs,
+ *pflags == NGHTTP3_DATA_FLAG_EOF?" EOF":"",
nwritten, Curl_bufq_len(&stream->sendbuf),
stream->upload_left));
return (nghttp3_ssize)nvecs;
@@ -1547,7 +1638,7 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf,
CURLcode *err)
{
struct cf_ngtcp2_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = NULL;
+ struct h3_stream_ctx *stream = NULL;
struct h1_req_parser h1;
struct dynhds h2_headers;
size_t nheader;
@@ -1614,16 +1705,19 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf,
else
/* data sending without specifying the data amount up front */
stream->upload_left = -1; /* unknown */
- reader.read_data = cb_h3_read_req_body;
- preader = &reader;
break;
default:
/* there is not request body */
stream->upload_left = 0; /* no request body */
- preader = NULL;
break;
}
+ stream->send_closed = (stream->upload_left == 0);
+ if(!stream->send_closed) {
+ reader.read_data = cb_h3_read_req_body;
+ preader = &reader;
+ }
+
rc = nghttp3_conn_submit_request(ctx->h3conn, stream->id,
nva, nheader, preader, data);
if(rc) {
@@ -1642,8 +1736,7 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf,
goto out;
}
- infof(data, "Using HTTP/3 Stream ID: %" PRId64 " (easy handle %p)",
- stream->id, (void *)data);
+ infof(data, "Using HTTP/3 Stream ID: %" PRId64, stream->id);
DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] opened for %s",
stream->id, data->state.url));
@@ -1658,20 +1751,23 @@ static ssize_t cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
const void *buf, size_t len, CURLcode *err)
{
struct cf_ngtcp2_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = H3_STREAM_CTX(data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
ssize_t sent = 0;
struct cf_call_data save;
+ struct pkt_io_ctx pktx;
+ CURLcode result;
CF_DATA_SAVE(save, cf, data);
DEBUGASSERT(cf->connected);
DEBUGASSERT(ctx->qconn);
DEBUGASSERT(ctx->h3conn);
+ pktx_init(&pktx, cf, data);
*err = CURLE_OK;
- if(stream && stream->closed) {
- *err = CURLE_HTTP3;
+ result = cf_progress_ingress(cf, data, &pktx);
+ if(result) {
+ *err = result;
sent = -1;
- goto out;
}
if(!stream || stream->id < 0) {
@@ -1681,32 +1777,66 @@ static ssize_t cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
goto out;
}
}
+ else if(stream->upload_blocked_len) {
+ /* the data in `buf` has alread been submitted or added to the
+ * buffers, but have been EAGAINed on the last invocation. */
+ DEBUGASSERT(len >= stream->upload_blocked_len);
+ if(len < stream->upload_blocked_len) {
+ /* Did we get called again with a smaller `len`? This should not
+ * happen. We are not prepared to handle that. */
+ failf(data, "HTTP/3 send again with decreased length");
+ *err = CURLE_HTTP3;
+ sent = -1;
+ goto out;
+ }
+ sent = (ssize_t)stream->upload_blocked_len;
+ stream->upload_blocked_len = 0;
+ }
+ else if(stream->closed) {
+ *err = CURLE_HTTP3;
+ sent = -1;
+ goto out;
+ }
else {
sent = Curl_bufq_write(&stream->sendbuf, buf, len, err);
DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] cf_send, add to "
"sendbuf(len=%zu) -> %zd, %d",
stream->id, len, sent, *err));
if(sent < 0) {
- if(*err == CURLE_AGAIN) {
- /* Can't add more to the send buf, needs to drain first.
- * Pause the sending to avoid a busy loop. */
- data->req.keepon |= KEEP_SEND_HOLD;
- DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] pause send",
- stream->id));
- }
goto out;
}
(void)nghttp3_conn_resume_stream(ctx->h3conn, stream->id);
}
- if(cf_flush_egress(cf, data)) {
- *err = CURLE_SEND_ERROR;
+ result = cf_progress_egress(cf, data, &pktx);
+ if(result) {
+ *err = result;
sent = -1;
- goto out;
+ }
+
+ if(stream && sent > 0 && stream->sendbuf_len_in_flight) {
+ /* We have unacknowledged DATA and cannot report success to our
+ * caller. Instead we EAGAIN and remember how much we have already
+ * "written" into our various internal connection buffers.
+ * We put the stream upload on HOLD, until this gets ACKed. */
+ stream->upload_blocked_len = sent;
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] cf_send(len=%zu), "
+ "%zu bytes in flight -> EGAIN", stream->id, len,
+ stream->sendbuf_len_in_flight));
+ *err = CURLE_AGAIN;
+ sent = -1;
+ data->req.keepon |= KEEP_SEND_HOLD;
}
out:
+ result = check_and_set_expiry(cf, data, &pktx);
+ if(result) {
+ *err = result;
+ sent = -1;
+ }
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] cf_send(len=%zu) -> %zd, %d",
+ stream? stream->id : -1, len, sent, *err));
CF_DATA_RESTORE(cf, save);
return sent;
}
@@ -1763,34 +1893,27 @@ static CURLcode qng_verify_peer(struct Curl_cfilter *cf,
return result;
}
-struct recv_ctx {
- struct Curl_cfilter *cf;
- struct Curl_easy *data;
- ngtcp2_tstamp ts;
- size_t pkt_count;
-};
-
static CURLcode recv_pkt(const unsigned char *pkt, size_t pktlen,
struct sockaddr_storage *remote_addr,
socklen_t remote_addrlen, int ecn,
void *userp)
{
- struct recv_ctx *r = userp;
- struct cf_ngtcp2_ctx *ctx = r->cf->ctx;
+ struct pkt_io_ctx *pktx = userp;
+ struct cf_ngtcp2_ctx *ctx = pktx->cf->ctx;
ngtcp2_pkt_info pi;
ngtcp2_path path;
int rv;
- ++r->pkt_count;
+ ++pktx->pkt_count;
ngtcp2_addr_init(&path.local, (struct sockaddr *)&ctx->q.local_addr,
ctx->q.local_addrlen);
ngtcp2_addr_init(&path.remote, (struct sockaddr *)remote_addr,
remote_addrlen);
pi.ecn = (uint32_t)ecn;
- rv = ngtcp2_conn_read_pkt(ctx->qconn, &path, &pi, pkt, pktlen, r->ts);
+ rv = ngtcp2_conn_read_pkt(ctx->qconn, &path, &pi, pkt, pktlen, pktx->ts);
if(rv) {
- DEBUGF(LOG_CF(r->data, r->cf, "ingress, read_pkt -> %s",
+ DEBUGF(LOG_CF(pktx->data, pktx->cf, "ingress, read_pkt -> %s",
ngtcp2_strerror(rv)));
if(!ctx->last_error.error_code) {
if(rv == NGTCP2_ERR_CRYPTO) {
@@ -1813,41 +1936,40 @@ static CURLcode recv_pkt(const unsigned char *pkt, size_t pktlen,
return CURLE_OK;
}
-static CURLcode cf_process_ingress(struct Curl_cfilter *cf,
- struct Curl_easy *data)
+static CURLcode cf_progress_ingress(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct pkt_io_ctx *pktx)
{
struct cf_ngtcp2_ctx *ctx = cf->ctx;
- struct recv_ctx rctx;
+ struct pkt_io_ctx local_pktx;
size_t pkts_chunk = 128, i;
size_t pkts_max = 10 * pkts_chunk;
- CURLcode result;
+ CURLcode result = CURLE_OK;
- rctx.cf = cf;
- rctx.data = data;
- rctx.ts = timestamp();
- rctx.pkt_count = 0;
+ if(!pktx) {
+ pktx_init(&local_pktx, cf, data);
+ pktx = &local_pktx;
+ }
+ else {
+ pktx->ts = timestamp();
+ }
for(i = 0; i < pkts_max; i += pkts_chunk) {
- rctx.pkt_count = 0;
+ pktx->pkt_count = 0;
result = vquic_recv_packets(cf, data, &ctx->q, pkts_chunk,
- recv_pkt, &rctx);
+ recv_pkt, pktx);
if(result) /* error */
break;
- if(rctx.pkt_count < pkts_chunk) /* got less than we could */
+ if(pktx->pkt_count < pkts_chunk) /* got less than we could */
break;
/* give egress a chance before we receive more */
- result = cf_flush_egress(cf, data);
+ result = cf_progress_egress(cf, data, pktx);
+ if(result) /* error */
+ break;
}
return result;
}
-struct read_ctx {
- struct Curl_cfilter *cf;
- struct Curl_easy *data;
- ngtcp2_tstamp ts;
- ngtcp2_path_storage *ps;
-};
-
/**
* Read a network packet to send from ngtcp2 into `buf`.
* Return number of bytes written or -1 with *err set.
@@ -1856,7 +1978,7 @@ static ssize_t read_pkt_to_send(void *userp,
unsigned char *buf, size_t buflen,
CURLcode *err)
{
- struct read_ctx *x = userp;
+ struct pkt_io_ctx *x = userp;
struct cf_ngtcp2_ctx *ctx = x->cf->ctx;
nghttp3_vec vec[16];
nghttp3_ssize veccnt;
@@ -1896,7 +2018,7 @@ static ssize_t read_pkt_to_send(void *userp,
flags = NGTCP2_WRITE_STREAM_FLAG_MORE |
(fin ? NGTCP2_WRITE_STREAM_FLAG_FIN : 0);
- n = ngtcp2_conn_writev_stream(ctx->qconn, x->ps? &x->ps->path : NULL,
+ n = ngtcp2_conn_writev_stream(ctx->qconn, &x->ps.path,
NULL, buf, buflen,
&ndatalen, flags, stream_id,
(const ngtcp2_vec *)vec, veccnt, x->ts);
@@ -1955,28 +2077,25 @@ out:
return nwritten;
}
-static CURLcode cf_flush_egress(struct Curl_cfilter *cf,
- struct Curl_easy *data)
+static CURLcode cf_progress_egress(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct pkt_io_ctx *pktx)
{
struct cf_ngtcp2_ctx *ctx = cf->ctx;
- int rv;
ssize_t nread;
size_t max_payload_size, path_max_payload_size, max_pktcnt;
size_t pktcnt = 0;
size_t gsolen = 0; /* this disables gso until we have a clue */
- ngtcp2_path_storage ps;
- ngtcp2_tstamp ts = timestamp();
- ngtcp2_tstamp expiry;
- ngtcp2_duration timeout;
CURLcode curlcode;
- struct read_ctx readx;
+ struct pkt_io_ctx local_pktx;
- rv = ngtcp2_conn_handle_expiry(ctx->qconn, ts);
- if(rv) {
- failf(data, "ngtcp2_conn_handle_expiry returned error: %s",
- ngtcp2_strerror(rv));
- ngtcp2_ccerr_set_liberr(&ctx->last_error, rv, NULL, 0);
- return CURLE_SEND_ERROR;
+ if(!pktx) {
+ pktx_init(&local_pktx, cf, data);
+ pktx = &local_pktx;
+ }
+ else {
+ pktx->ts = timestamp();
+ ngtcp2_path_storage_zero(&pktx->ps);
}
curlcode = vquic_flush(cf, data, &ctx->q);
@@ -1988,8 +2107,6 @@ static CURLcode cf_flush_egress(struct Curl_cfilter *cf,
return curlcode;
}
- ngtcp2_path_storage_zero(&ps);
-
/* In UDP, there is a maximum theoretical packet paload length and
* a minimum payload length that is "guarantueed" to work.
* To detect if this minimum payload can be increased, ngtcp2 sends
@@ -2008,15 +2125,10 @@ static CURLcode cf_flush_egress(struct Curl_cfilter *cf,
max_pktcnt = CURLMIN(MAX_PKT_BURST,
ctx->q.sendbuf.chunk_size / max_payload_size);
- readx.cf = cf;
- readx.data = data;
- readx.ts = ts;
- readx.ps = &ps;
-
for(;;) {
/* add the next packet to send, if any, to our buffer */
nread = Curl_bufq_sipn(&ctx->q.sendbuf, max_payload_size,
- read_pkt_to_send, &readx, &curlcode);
+ read_pkt_to_send, pktx, &curlcode);
/* DEBUGF(LOG_CF(data, cf, "sip packet(maxlen=%zu) -> %zd, %d",
max_payload_size, nread, curlcode)); */
if(nread < 0) {
@@ -2076,21 +2188,6 @@ static CURLcode cf_flush_egress(struct Curl_cfilter *cf,
}
out:
- /* non-errored exit. check when we should run again. */
- expiry = ngtcp2_conn_get_expiry(ctx->qconn);
- if(expiry != UINT64_MAX) {
- if(expiry <= ts) {
- timeout = 0;
- }
- else {
- timeout = expiry - ts;
- if(timeout % NGTCP2_MILLISECONDS) {
- timeout += NGTCP2_MILLISECONDS;
- }
- }
- Curl_expire(data, timeout / NGTCP2_MILLISECONDS, EXPIRE_QUIC);
- }
-
return CURLE_OK;
}
@@ -2101,7 +2198,7 @@ out:
static bool cf_ngtcp2_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data)
{
- const struct stream_ctx *stream = H3_STREAM_CTX(data);
+ const struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
(void)cf;
return stream && !Curl_bufq_is_empty(&stream->recvbuf);
}
@@ -2113,7 +2210,7 @@ static CURLcode h3_data_pause(struct Curl_cfilter *cf,
/* TODO: there seems right now no API in ngtcp2 to shrink/enlarge
* the streams windows. As we do in HTTP/2. */
if(!pause) {
- drain_stream(cf, data);
+ h3_drain_stream(cf, data);
Curl_expire(data, 0, EXPIRE_RUN_NOW);
}
return CURLE_OK;
@@ -2141,7 +2238,7 @@ static CURLcode cf_ngtcp2_data_event(struct Curl_cfilter *cf,
break;
}
case CF_CTRL_DATA_DONE_SEND: {
- struct stream_ctx *stream = H3_STREAM_CTX(data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
if(stream && !stream->send_closed) {
stream->send_closed = TRUE;
stream->upload_left = Curl_bufq_len(&stream->sendbuf);
@@ -2150,11 +2247,7 @@ static CURLcode cf_ngtcp2_data_event(struct Curl_cfilter *cf,
break;
}
case CF_CTRL_DATA_IDLE:
- if(timestamp() >= ngtcp2_conn_get_expiry(ctx->qconn)) {
- if(cf_flush_egress(cf, data)) {
- result = CURLE_SEND_ERROR;
- }
- }
+ result = check_and_set_expiry(cf, data, NULL);
break;
default:
break;
@@ -2250,7 +2343,8 @@ static void cf_ngtcp2_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
* Might be called twice for happy eyeballs.
*/
static CURLcode cf_connect_start(struct Curl_cfilter *cf,
- struct Curl_easy *data)
+ struct Curl_easy *data,
+ struct pkt_io_ctx *pktx)
{
struct cf_ngtcp2_ctx *ctx = cf->ctx;
int rc;
@@ -2294,7 +2388,7 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
(void)Curl_qlogdir(data, ctx->scid.data, NGTCP2_MAX_CIDLEN, &qfd);
ctx->qlogfd = qfd; /* -1 if failure above */
- quic_settings(ctx, data);
+ quic_settings(ctx, data, pktx);
result = vquic_ctx_init(&ctx->q);
if(result)
@@ -2344,6 +2438,7 @@ static CURLcode cf_ngtcp2_connect(struct Curl_cfilter *cf,
CURLcode result = CURLE_OK;
struct cf_call_data save;
struct curltime now;
+ struct pkt_io_ctx pktx;
if(cf->connected) {
*done = TRUE;
@@ -2359,6 +2454,7 @@ static CURLcode cf_ngtcp2_connect(struct Curl_cfilter *cf,
*done = FALSE;
now = Curl_now();
+ pktx_init(&pktx, cf, data);
CF_DATA_SAVE(save, cf, data);
@@ -2370,19 +2466,19 @@ static CURLcode cf_ngtcp2_connect(struct Curl_cfilter *cf,
if(!ctx->qconn) {
ctx->started_at = now;
- result = cf_connect_start(cf, data);
+ result = cf_connect_start(cf, data, &pktx);
if(result)
goto out;
- result = cf_flush_egress(cf, data);
+ result = cf_progress_egress(cf, data, &pktx);
/* we do not expect to be able to recv anything yet */
goto out;
}
- result = cf_process_ingress(cf, data);
+ result = cf_progress_ingress(cf, data, &pktx);
if(result)
goto out;
- result = cf_flush_egress(cf, data);
+ result = cf_progress_egress(cf, data, &pktx);
if(result)
goto out;
@@ -2402,7 +2498,7 @@ static CURLcode cf_ngtcp2_connect(struct Curl_cfilter *cf,
out:
if(result == CURLE_RECV_ERROR && ctx->qconn &&
- ngtcp2_conn_is_in_draining_period(ctx->qconn)) {
+ ngtcp2_conn_in_draining_period(ctx->qconn)) {
/* When a QUIC server instance is shutting down, it may send us a
* CONNECTION_CLOSE right away. Our connection then enters the DRAINING
* state.
@@ -2439,6 +2535,9 @@ out:
r_ip, r_port, curl_easy_strerror(result));
}
#endif
+ if(!result && ctx->qconn) {
+ result = check_and_set_expiry(cf, data, &pktx);
+ }
DEBUGF(LOG_CF(data, cf, "connect -> %d, done=%d", result, *done));
CF_DATA_RESTORE(cf, save);
return result;
@@ -2510,13 +2609,11 @@ static bool cf_ngtcp2_conn_is_alive(struct Curl_cfilter *cf,
not in use by any other transfer, there shouldn't be any data here,
only "protocol frames" */
*input_pending = FALSE;
- Curl_attach_connection(data, cf->conn);
- if(cf_process_ingress(cf, data))
+ if(cf_progress_ingress(cf, data, NULL))
alive = FALSE;
else {
alive = TRUE;
}
- Curl_detach_connection(data);
}
return alive;
diff --git a/Utilities/cmcurl/lib/vquic/curl_quiche.c b/Utilities/cmcurl/lib/vquic/curl_quiche.c
index 3a4f9f9..39cc16e 100644
--- a/Utilities/cmcurl/lib/vquic/curl_quiche.c
+++ b/Utilities/cmcurl/lib/vquic/curl_quiche.c
@@ -277,7 +277,7 @@ static CURLcode h3_data_setup(struct Curl_cfilter *cf,
stream->id = -1;
Curl_bufq_initp(&stream->recvbuf, &ctx->stream_bufcp,
H3_STREAM_RECV_CHUNKS, BUFQ_OPT_SOFT_LIMIT);
- DEBUGF(LOG_CF(data, cf, "data setup (easy %p)", (void *)data));
+ DEBUGF(LOG_CF(data, cf, "data setup"));
return CURLE_OK;
}
@@ -329,7 +329,7 @@ static struct Curl_easy *get_stream_easy(struct Curl_cfilter *cf,
else {
DEBUGASSERT(data->multi);
for(sdata = data->multi->easyp; sdata; sdata = sdata->next) {
- if(H3_STREAM_ID(sdata) == stream3_id) {
+ if((sdata->conn == data->conn) && H3_STREAM_ID(sdata) == stream3_id) {
return sdata;
}
}
@@ -425,12 +425,8 @@ static ssize_t stream_resp_read(void *reader_ctx,
*err = CURLE_OK;
return nread;
}
- else if(nread < 0) {
- *err = CURLE_AGAIN;
- return -1;
- }
else {
- *err = stream->resp_got_header? CURLE_PARTIAL_FILE : CURLE_RECV_ERROR;
+ *err = CURLE_AGAIN;
return -1;
}
}
@@ -461,8 +457,8 @@ static CURLcode cf_recv_body(struct Curl_cfilter *cf,
if(nwritten < 0 && result != CURLE_AGAIN) {
DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"] recv_body error %zd",
stream->id, nwritten));
- failf(data, "Error %zd in HTTP/3 response body for stream[%"PRId64"]",
- nwritten, stream->id);
+ failf(data, "Error %d in HTTP/3 response body for stream[%"PRId64"]",
+ result, stream->id);
stream->closed = TRUE;
stream->reset = TRUE;
stream->send_closed = TRUE;
@@ -595,8 +591,13 @@ static CURLcode cf_poll_events(struct Curl_cfilter *cf,
"for [h3sid=%"PRId64"] -> %d",
stream? stream->id : -1, cf_ev_name(ev),
stream3_id, result));
- quiche_h3_event_free(ev);
- return result;
+ if(data == sdata) {
+ /* Only report this error to the caller if it is about the
+ * transfer we were called with. Otherwise we fail a transfer
+ * due to a problem in another one. */
+ quiche_h3_event_free(ev);
+ return result;
+ }
}
quiche_h3_event_free(ev);
}
@@ -649,7 +650,7 @@ static CURLcode recv_pkt(const unsigned char *pkt, size_t pktlen,
}
}
else if((size_t)nread < pktlen) {
- DEBUGF(LOG_CF(r->data, r->cf, "ingress, quiche only read %zd/%zd bytes",
+ DEBUGF(LOG_CF(r->data, r->cf, "ingress, quiche only read %zd/%zu bytes",
nread, pktlen));
}
@@ -826,7 +827,7 @@ static ssize_t cf_quiche_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
if(!stream) {
*err = CURLE_RECV_ERROR;
- goto out;
+ return -1;
}
if(!Curl_bufq_is_empty(&stream->recvbuf)) {
@@ -883,8 +884,10 @@ out:
}
if(nread > 0)
ctx->data_recvd += nread;
- DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"] cf_recv(total=%zd) -> %zd, %d",
- stream->id, ctx->data_recvd, nread, *err));
+ DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"] cf_recv(total=%"
+ CURL_FORMAT_CURL_OFF_T ") -> %zd, %d",
+ stream ? stream->id : (int64_t)0,
+ ctx->data_recvd, nread, *err));
return nread;
}
@@ -909,8 +912,7 @@ static ssize_t h3_open_stream(struct Curl_cfilter *cf,
if(!stream) {
*err = h3_data_setup(cf, data);
if(*err) {
- nwritten = -1;
- goto out;
+ return -1;
}
stream = H3_STREAM_CTX(data);
DEBUGASSERT(stream);
@@ -995,8 +997,7 @@ static ssize_t h3_open_stream(struct Curl_cfilter *cf,
stream->closed = FALSE;
stream->reset = FALSE;
- infof(data, "Using HTTP/3 Stream ID: %" PRId64 " (easy handle %p)",
- stream3_id, (void *)data);
+ infof(data, "Using HTTP/3 Stream ID: %" PRId64, stream3_id);
DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] opened for %s",
stream3_id, data->state.url));
@@ -1068,7 +1069,7 @@ static ssize_t cf_quiche_send(struct Curl_cfilter *cf, struct Curl_easy *data,
stream->send_closed = TRUE;
DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] send body(len=%zu, "
- "left=%zd) -> %zd",
+ "left=%" CURL_FORMAT_CURL_OFF_T ") -> %zd",
stream->id, len, stream->upload_left, nwritten));
*err = CURLE_OK;
}
@@ -1151,10 +1152,8 @@ static CURLcode cf_quiche_data_event(struct Curl_cfilter *cf,
(void)arg1;
(void)arg2;
switch(event) {
- case CF_CTRL_DATA_SETUP: {
- result = h3_data_setup(cf, data);
+ case CF_CTRL_DATA_SETUP:
break;
- }
case CF_CTRL_DATA_PAUSE:
result = h3_data_pause(cf, data, (arg1 != 0));
break;
@@ -1343,11 +1342,6 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
}
#endif
- /* we do not get a setup event for the initial transfer */
- result = h3_data_setup(cf, data);
- if(result)
- return result;
-
result = cf_flush_egress(cf, data);
if(result)
return result;
@@ -1555,13 +1549,11 @@ static bool cf_quiche_conn_is_alive(struct Curl_cfilter *cf,
not in use by any other transfer, there shouldn't be any data here,
only "protocol frames" */
*input_pending = FALSE;
- Curl_attach_connection(data, cf->conn);
if(cf_process_ingress(cf, data))
alive = FALSE;
else {
alive = TRUE;
}
- Curl_detach_connection(data);
}
return alive;
diff --git a/Utilities/cmcurl/lib/vquic/vquic.c b/Utilities/cmcurl/lib/vquic/vquic.c
index f850029..399de0b 100644
--- a/Utilities/cmcurl/lib/vquic/vquic.c
+++ b/Utilities/cmcurl/lib/vquic/vquic.c
@@ -362,7 +362,7 @@ static CURLcode recvmmsg_packets(struct Curl_cfilter *cf,
}
out:
- DEBUGF(LOG_CF(data, cf, "recvd %zu packets with %zd bytes -> %d",
+ DEBUGF(LOG_CF(data, cf, "recvd %zu packets with %zu bytes -> %d",
pkts, total_nread, result));
return result;
}
@@ -425,7 +425,7 @@ static CURLcode recvmsg_packets(struct Curl_cfilter *cf,
}
out:
- DEBUGF(LOG_CF(data, cf, "recvd %zu packets with %zd bytes -> %d",
+ DEBUGF(LOG_CF(data, cf, "recvd %zu packets with %zu bytes -> %d",
pkts, total_nread, result));
return result;
}
@@ -482,7 +482,7 @@ static CURLcode recvfrom_packets(struct Curl_cfilter *cf,
}
out:
- DEBUGF(LOG_CF(data, cf, "recvd %zu packets with %zd bytes -> %d",
+ DEBUGF(LOG_CF(data, cf, "recvd %zu packets with %zu bytes -> %d",
pkts, total_nread, result));
return result;
}
diff --git a/Utilities/cmcurl/lib/vssh/libssh2.c b/Utilities/cmcurl/lib/vssh/libssh2.c
index 14c2784..98fce51 100644
--- a/Utilities/cmcurl/lib/vssh/libssh2.c
+++ b/Utilities/cmcurl/lib/vssh/libssh2.c
@@ -100,11 +100,9 @@
/* Local functions: */
static const char *sftp_libssh2_strerror(unsigned long err);
-#ifdef CURL_LIBSSH2_DEBUG
static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc);
static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc);
static LIBSSH2_FREE_FUNC(my_libssh2_free);
-#endif
static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data);
static CURLcode ssh_connect(struct Curl_easy *data, bool *done);
static CURLcode ssh_multi_statemach(struct Curl_easy *data, bool *done);
@@ -284,8 +282,6 @@ static CURLcode libssh2_session_error_to_CURLE(int err)
return CURLE_SSH;
}
-#ifdef CURL_LIBSSH2_DEBUG
-
static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc)
{
(void)abstract; /* arg not used */
@@ -305,8 +301,6 @@ static LIBSSH2_FREE_FUNC(my_libssh2_free)
free(ptr);
}
-#endif
-
/*
* SSH State machine related code
*/
@@ -895,6 +889,7 @@ static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data)
}
if(found) {
+ int rc;
infof(data, "Found host %s in %s",
conn->host.name, data->set.str[STRING_SSH_KNOWNHOSTS]);
@@ -944,9 +939,15 @@ static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data)
}
infof(data, "Set \"%s\" as SSH hostkey type", hostkey_method);
- result = libssh2_session_error_to_CURLE(
- libssh2_session_method_pref(
- sshc->ssh_session, LIBSSH2_METHOD_HOSTKEY, hostkey_method));
+ rc = libssh2_session_method_pref(sshc->ssh_session,
+ LIBSSH2_METHOD_HOSTKEY, hostkey_method);
+ if(rc) {
+ char *errmsg = NULL;
+ int errlen;
+ libssh2_session_last_error(sshc->ssh_session, &errmsg, &errlen, 0);
+ failf(data, "libssh2: %s", errmsg);
+ result = libssh2_session_error_to_CURLE(rc);
+ }
}
else {
infof(data, "Did not find host %s in %s",
@@ -3268,13 +3269,12 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done)
sock = conn->sock[FIRSTSOCKET];
#endif /* CURL_LIBSSH2_DEBUG */
-#ifdef CURL_LIBSSH2_DEBUG
+ /* libcurl MUST to set custom memory functions so that the kbd_callback
+ funciton's memory allocations can be properled freed */
sshc->ssh_session = libssh2_session_init_ex(my_libssh2_malloc,
my_libssh2_free,
my_libssh2_realloc, data);
-#else
- sshc->ssh_session = libssh2_session_init_ex(NULL, NULL, NULL, data);
-#endif
+
if(!sshc->ssh_session) {
failf(data, "Failure initialising ssh session");
return CURLE_FAILED_INIT;
diff --git a/Utilities/cmcurl/lib/vssh/wolfssh.c b/Utilities/cmcurl/lib/vssh/wolfssh.c
index 780b612..b47c231 100644
--- a/Utilities/cmcurl/lib/vssh/wolfssh.c
+++ b/Utilities/cmcurl/lib/vssh/wolfssh.c
@@ -277,7 +277,7 @@ static ssize_t wsftp_send(struct Curl_easy *data, int sockindex,
return -1;
}
DEBUGASSERT(rc == (int)len);
- infof(data, "sent %zd bytes SFTP from offset %zd",
+ infof(data, "sent %zu bytes SFTP from offset %" CURL_FORMAT_CURL_OFF_T,
len, sshc->offset);
sshc->offset += len;
return (ssize_t)rc;
diff --git a/Utilities/cmcurl/lib/vtls/bearssl.c b/Utilities/cmcurl/lib/vtls/bearssl.c
index 2b666ca..6ed453b 100644
--- a/Utilities/cmcurl/lib/vtls/bearssl.c
+++ b/Utilities/cmcurl/lib/vtls/bearssl.c
@@ -52,7 +52,7 @@ struct x509_context {
int cert_num;
};
-struct ssl_backend_data {
+struct bearssl_ssl_backend_data {
br_ssl_client_context ctx;
struct x509_context x509;
unsigned char buf[BR_SSL_BUFSIZE_BIDI];
@@ -574,7 +574,8 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct bearssl_ssl_backend_data *backend =
+ (struct bearssl_ssl_backend_data *)connssl->backend;
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
@@ -751,7 +752,8 @@ static CURLcode bearssl_run_until(struct Curl_cfilter *cf,
unsigned target)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct bearssl_ssl_backend_data *backend =
+ (struct bearssl_ssl_backend_data *)connssl->backend;
unsigned state;
unsigned char *buf;
size_t len;
@@ -820,7 +822,8 @@ static CURLcode bearssl_connect_step2(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct bearssl_ssl_backend_data *backend =
+ (struct bearssl_ssl_backend_data *)connssl->backend;
CURLcode ret;
DEBUGASSERT(backend);
@@ -842,7 +845,8 @@ static CURLcode bearssl_connect_step3(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct bearssl_ssl_backend_data *backend =
+ (struct bearssl_ssl_backend_data *)connssl->backend;
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
CURLcode ret;
@@ -889,7 +893,8 @@ static ssize_t bearssl_send(struct Curl_cfilter *cf, struct Curl_easy *data,
const void *buf, size_t len, CURLcode *err)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct bearssl_ssl_backend_data *backend =
+ (struct bearssl_ssl_backend_data *)connssl->backend;
unsigned char *app;
size_t applen;
@@ -923,7 +928,8 @@ static ssize_t bearssl_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
char *buf, size_t len, CURLcode *err)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct bearssl_ssl_backend_data *backend =
+ (struct bearssl_ssl_backend_data *)connssl->backend;
unsigned char *app;
size_t applen;
@@ -1050,10 +1056,12 @@ static bool bearssl_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data)
{
struct ssl_connect_data *ctx = cf->ctx;
+ struct bearssl_ssl_backend_data *backend;
(void)data;
DEBUGASSERT(ctx && ctx->backend);
- return br_ssl_engine_current_state(&ctx->backend->ctx.eng) & BR_SSL_RECVAPP;
+ backend = (struct bearssl_ssl_backend_data *)ctx->backend;
+ return br_ssl_engine_current_state(&backend->ctx.eng) & BR_SSL_RECVAPP;
}
static CURLcode bearssl_random(struct Curl_easy *data UNUSED_PARAM,
@@ -1101,7 +1109,8 @@ static CURLcode bearssl_connect_nonblocking(struct Curl_cfilter *cf,
static void *bearssl_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM)
{
- struct ssl_backend_data *backend = connssl->backend;
+ struct bearssl_ssl_backend_data *backend =
+ (struct bearssl_ssl_backend_data *)connssl->backend;
DEBUGASSERT(backend);
return &backend->ctx;
}
@@ -1109,7 +1118,8 @@ static void *bearssl_get_internals(struct ssl_connect_data *connssl,
static void bearssl_close(struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct bearssl_ssl_backend_data *backend =
+ (struct bearssl_ssl_backend_data *)connssl->backend;
size_t i;
DEBUGASSERT(backend);
@@ -1147,7 +1157,7 @@ static CURLcode bearssl_sha256sum(const unsigned char *input,
const struct Curl_ssl Curl_ssl_bearssl = {
{ CURLSSLBACKEND_BEARSSL, "bearssl" }, /* info */
SSLSUPP_CAINFO_BLOB | SSLSUPP_SSL_CTX | SSLSUPP_HTTPS_PROXY,
- sizeof(struct ssl_backend_data),
+ sizeof(struct bearssl_ssl_backend_data),
Curl_none_init, /* init */
Curl_none_cleanup, /* cleanup */
diff --git a/Utilities/cmcurl/lib/vtls/gskit.c b/Utilities/cmcurl/lib/vtls/gskit.c
index 749dc91..c128293 100644
--- a/Utilities/cmcurl/lib/vtls/gskit.c
+++ b/Utilities/cmcurl/lib/vtls/gskit.c
@@ -103,14 +103,14 @@
#define CURL_GSKPROTO_TLSV12_MASK (1 << CURL_GSKPROTO_TLSV12)
#define CURL_GSKPROTO_LAST 5
-struct ssl_backend_data {
+struct gskit_ssl_backend_data {
gsk_handle handle;
int iocport;
int localfd;
int remotefd;
};
-#define BACKEND connssl->backend
+#define BACKEND ((struct gskit_ssl_backend_data *)connssl->backend)
/* Supported ciphers. */
struct gskit_cipher {
@@ -518,6 +518,7 @@ static int pipe_ssloverssl(struct Curl_cfilter *cf, struct Curl_easy *data,
struct Curl_cfilter *cf_ssl_next = Curl_ssl_cf_get_ssl(cf->next);
struct ssl_connect_data *connssl_next = cf_ssl_next?
cf_ssl_next->ctx : NULL;
+ struct gskit_ssl_backend_data *backend_next;
struct pollfd fds[2];
int n;
int m;
@@ -531,6 +532,8 @@ static int pipe_ssloverssl(struct Curl_cfilter *cf, struct Curl_easy *data,
return 0; /* No SSL over SSL: OK. */
DEBUGASSERT(connssl_next->backend);
+ backend_next = (struct gskit_ssl_backend_data *)connssl_next->backend;
+
n = 1;
fds[0].fd = BACKEND->remotefd;
fds[1].fd = Curl_conn_cf_get_socket(cf, data);
@@ -550,8 +553,7 @@ static int pipe_ssloverssl(struct Curl_cfilter *cf, struct Curl_easy *data,
if(fds[0].revents & POLLOUT) {
/* Try getting data from HTTPS proxy and pipe it upstream. */
n = 0;
- i = gsk_secure_soc_read(connssl_next->backend->handle,
- buf, sizeof(buf), &n);
+ i = gsk_secure_soc_read(backend_next->handle, buf, sizeof(buf), &n);
switch(i) {
case GSK_OK:
if(n) {
@@ -575,7 +577,7 @@ static int pipe_ssloverssl(struct Curl_cfilter *cf, struct Curl_easy *data,
if(n < 0)
return -1;
if(n) {
- i = gsk_secure_soc_write(connssl_next->backend->handle, buf, n, &m);
+ i = gsk_secure_soc_write(backend_next->handle, buf, n, &m);
if(i != GSK_OK || n != m)
return -1;
ret = 1;
@@ -1294,7 +1296,7 @@ const struct Curl_ssl Curl_ssl_gskit = {
SSLSUPP_CERTINFO |
SSLSUPP_PINNEDPUBKEY,
- sizeof(struct ssl_backend_data),
+ sizeof(struct gskit_ssl_backend_data),
gskit_init, /* init */
gskit_cleanup, /* cleanup */
diff --git a/Utilities/cmcurl/lib/vtls/gtls.c b/Utilities/cmcurl/lib/vtls/gtls.c
index 3d1906e..f6f1e10 100644
--- a/Utilities/cmcurl/lib/vtls/gtls.c
+++ b/Utilities/cmcurl/lib/vtls/gtls.c
@@ -76,7 +76,7 @@ static bool gtls_inited = FALSE;
# include <gnutls/ocsp.h>
-struct ssl_backend_data {
+struct gtls_ssl_backend_data {
struct gtls_instance gtls;
};
@@ -91,7 +91,9 @@ static ssize_t gtls_push(void *s, const void *buf, size_t blen)
DEBUGASSERT(data);
nwritten = Curl_conn_cf_send(cf->next, data, buf, blen, &result);
if(nwritten < 0) {
- gnutls_transport_set_errno(connssl->backend->gtls.session,
+ struct gtls_ssl_backend_data *backend =
+ (struct gtls_ssl_backend_data *)connssl->backend;
+ gnutls_transport_set_errno(backend->gtls.session,
(CURLE_AGAIN == result)? EAGAIN : EINVAL);
nwritten = -1;
}
@@ -109,7 +111,9 @@ static ssize_t gtls_pull(void *s, void *buf, size_t blen)
DEBUGASSERT(data);
nread = Curl_conn_cf_recv(cf->next, data, buf, blen, &result);
if(nread < 0) {
- gnutls_transport_set_errno(connssl->backend->gtls.session,
+ struct gtls_ssl_backend_data *backend =
+ (struct gtls_ssl_backend_data *)connssl->backend;
+ gnutls_transport_set_errno(backend->gtls.session,
(CURLE_AGAIN == result)? EAGAIN : EINVAL);
nread = -1;
}
@@ -212,7 +216,8 @@ static CURLcode handshake(struct Curl_cfilter *cf,
bool nonblocking)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct gtls_ssl_backend_data *backend =
+ (struct gtls_ssl_backend_data *)connssl->backend;
gnutls_session_t session;
curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
@@ -679,7 +684,8 @@ static CURLcode
gtls_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct gtls_ssl_backend_data *backend =
+ (struct gtls_ssl_backend_data *)connssl->backend;
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
long * const pverifyresult = &ssl_config->certverifyresult;
@@ -1346,7 +1352,8 @@ gtls_connect_common(struct Curl_cfilter *cf,
/* Finish connecting once the handshake is done */
if(ssl_connect_1 == connssl->connecting_state) {
- struct ssl_backend_data *backend = connssl->backend;
+ struct gtls_ssl_backend_data *backend =
+ (struct gtls_ssl_backend_data *)connssl->backend;
gnutls_session_t session;
DEBUGASSERT(backend);
session = backend->gtls.session;
@@ -1390,11 +1397,13 @@ static bool gtls_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data)
{
struct ssl_connect_data *ctx = cf->ctx;
+ struct gtls_ssl_backend_data *backend;
(void)data;
DEBUGASSERT(ctx && ctx->backend);
- if(ctx->backend->gtls.session &&
- 0 != gnutls_record_check_pending(ctx->backend->gtls.session))
+ backend = (struct gtls_ssl_backend_data *)ctx->backend;
+ if(backend->gtls.session &&
+ 0 != gnutls_record_check_pending(backend->gtls.session))
return TRUE;
return FALSE;
}
@@ -1406,7 +1415,8 @@ static ssize_t gtls_send(struct Curl_cfilter *cf,
CURLcode *curlcode)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct gtls_ssl_backend_data *backend =
+ (struct gtls_ssl_backend_data *)connssl->backend;
ssize_t rc;
(void)data;
@@ -1428,7 +1438,8 @@ static void gtls_close(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct gtls_ssl_backend_data *backend =
+ (struct gtls_ssl_backend_data *)connssl->backend;
(void) data;
DEBUGASSERT(backend);
@@ -1463,7 +1474,8 @@ static int gtls_shutdown(struct Curl_cfilter *cf,
{
struct ssl_connect_data *connssl = cf->ctx;
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
- struct ssl_backend_data *backend = connssl->backend;
+ struct gtls_ssl_backend_data *backend =
+ (struct gtls_ssl_backend_data *)connssl->backend;
int retval = 0;
DEBUGASSERT(backend);
@@ -1541,7 +1553,8 @@ static ssize_t gtls_recv(struct Curl_cfilter *cf,
CURLcode *curlcode)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct gtls_ssl_backend_data *backend =
+ (struct gtls_ssl_backend_data *)connssl->backend;
ssize_t ret;
(void)data;
@@ -1620,7 +1633,8 @@ static bool gtls_cert_status_request(void)
static void *gtls_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM)
{
- struct ssl_backend_data *backend = connssl->backend;
+ struct gtls_ssl_backend_data *backend =
+ (struct gtls_ssl_backend_data *)connssl->backend;
(void)info;
DEBUGASSERT(backend);
return backend->gtls.session;
@@ -1634,7 +1648,7 @@ const struct Curl_ssl Curl_ssl_gnutls = {
SSLSUPP_PINNEDPUBKEY |
SSLSUPP_HTTPS_PROXY,
- sizeof(struct ssl_backend_data),
+ sizeof(struct gtls_ssl_backend_data),
gtls_init, /* init */
gtls_cleanup, /* cleanup */
diff --git a/Utilities/cmcurl/lib/vtls/mbedtls.c b/Utilities/cmcurl/lib/vtls/mbedtls.c
index d95888c..8d0fa39 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls.c
+++ b/Utilities/cmcurl/lib/vtls/mbedtls.c
@@ -81,7 +81,7 @@
# endif
#endif
-struct ssl_backend_data {
+struct mbed_ssl_backend_data {
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_entropy_context entropy;
mbedtls_ssl_context ssl;
@@ -255,7 +255,8 @@ static CURLcode
set_ssl_version_min_max(struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct mbed_ssl_backend_data *backend =
+ (struct mbed_ssl_backend_data *)connssl->backend;
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
int mbedtls_ver_min = MBEDTLS_SSL_MINOR_VERSION_3;
@@ -307,7 +308,8 @@ static CURLcode
mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct mbed_ssl_backend_data *backend =
+ (struct mbed_ssl_backend_data *)connssl->backend;
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
@@ -697,7 +699,8 @@ mbed_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
{
int ret;
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct mbed_ssl_backend_data *backend =
+ (struct mbed_ssl_backend_data *)connssl->backend;
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
const mbedtls_x509_crt *peercert;
const char * const pinnedpubkey = Curl_ssl_cf_is_proxy(cf)?
@@ -860,7 +863,8 @@ mbed_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
{
CURLcode retcode = CURLE_OK;
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct mbed_ssl_backend_data *backend =
+ (struct mbed_ssl_backend_data *)connssl->backend;
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
@@ -915,7 +919,8 @@ static ssize_t mbed_send(struct Curl_cfilter *cf, struct Curl_easy *data,
CURLcode *curlcode)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct mbed_ssl_backend_data *backend =
+ (struct mbed_ssl_backend_data *)connssl->backend;
int ret = -1;
(void)data;
@@ -939,7 +944,8 @@ static void mbedtls_close_all(struct Curl_easy *data)
static void mbedtls_close(struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct mbed_ssl_backend_data *backend =
+ (struct mbed_ssl_backend_data *)connssl->backend;
char buf[32];
(void)data;
@@ -968,7 +974,8 @@ static ssize_t mbed_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
CURLcode *curlcode)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct mbed_ssl_backend_data *backend =
+ (struct mbed_ssl_backend_data *)connssl->backend;
int ret = -1;
ssize_t len = -1;
@@ -1204,10 +1211,12 @@ static bool mbedtls_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data)
{
struct ssl_connect_data *ctx = cf->ctx;
+ struct mbed_ssl_backend_data *backend;
(void)data;
DEBUGASSERT(ctx && ctx->backend);
- return mbedtls_ssl_get_bytes_avail(&ctx->backend->ssl) != 0;
+ backend = (struct mbed_ssl_backend_data *)ctx->backend;
+ return mbedtls_ssl_get_bytes_avail(&backend->ssl) != 0;
}
static CURLcode mbedtls_sha256sum(const unsigned char *input,
@@ -1234,7 +1243,8 @@ static CURLcode mbedtls_sha256sum(const unsigned char *input,
static void *mbedtls_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM)
{
- struct ssl_backend_data *backend = connssl->backend;
+ struct mbed_ssl_backend_data *backend =
+ (struct mbed_ssl_backend_data *)connssl->backend;
(void)info;
DEBUGASSERT(backend);
return &backend->ssl;
@@ -1249,7 +1259,7 @@ const struct Curl_ssl Curl_ssl_mbedtls = {
SSLSUPP_SSL_CTX |
SSLSUPP_HTTPS_PROXY,
- sizeof(struct ssl_backend_data),
+ sizeof(struct mbed_ssl_backend_data),
mbedtls_init, /* init */
mbedtls_cleanup, /* cleanup */
diff --git a/Utilities/cmcurl/lib/vtls/nss.c b/Utilities/cmcurl/lib/vtls/nss.c
index 5e5dbb7..322f507 100644
--- a/Utilities/cmcurl/lib/vtls/nss.c
+++ b/Utilities/cmcurl/lib/vtls/nss.c
@@ -81,7 +81,7 @@
/* enough to fit the string "PEM Token #[0|1]" */
#define SLOTSIZE 13
-struct ssl_backend_data {
+struct nss_ssl_backend_data {
PRFileDesc *handle;
char *client_nickname;
struct Curl_easy *data;
@@ -489,7 +489,8 @@ static CURLcode nss_create_object(struct ssl_connect_data *connssl,
const int slot_id = (cacert) ? 0 : 1;
char *slot_name = aprintf("PEM Token #%d", slot_id);
- struct ssl_backend_data *backend = connssl->backend;
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
DEBUGASSERT(backend);
@@ -806,7 +807,9 @@ static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig,
struct Curl_cfilter *cf = (struct Curl_cfilter *)arg;
struct ssl_connect_data *connssl = cf->ctx;
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
- struct Curl_easy *data = connssl->backend->data;
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
+ struct Curl_easy *data = backend->data;
DEBUGASSERT(data);
#ifdef SSL_ENABLE_OCSP_STAPLING
@@ -851,7 +854,9 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg)
{
struct Curl_cfilter *cf = (struct Curl_cfilter *)arg;
struct ssl_connect_data *connssl = cf->ctx;
- struct Curl_easy *data = connssl->backend->data;
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
+ struct Curl_easy *data = backend->data;
unsigned int buflenmax = 50;
unsigned char buf[50];
unsigned int buflen;
@@ -1055,7 +1060,9 @@ static SECStatus BadCertHandler(void *arg, PRFileDesc *sock)
{
struct Curl_cfilter *cf = (struct Curl_cfilter *)arg;
struct ssl_connect_data *connssl = cf->ctx;
- struct Curl_easy *data = connssl->backend->data;
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
+ struct Curl_easy *data = backend->data;
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
struct ssl_config_data *ssl_config;
PRErrorCode err = PR_GetError();
@@ -1117,7 +1124,8 @@ static CURLcode cmp_peer_pubkey(struct ssl_connect_data *connssl,
const char *pinnedpubkey)
{
CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
- struct ssl_backend_data *backend = connssl->backend;
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
struct Curl_easy *data = NULL;
CERTCertificate *cert;
@@ -1173,7 +1181,8 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock,
struct SECKEYPrivateKeyStr **pRetKey)
{
struct ssl_connect_data *connssl = (struct ssl_connect_data *)arg;
- struct ssl_backend_data *backend = connssl->backend;
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
struct Curl_easy *data = NULL;
const char *nickname = NULL;
static const char pem_slotname[] = "PEM Token #1";
@@ -1538,7 +1547,8 @@ static void nss_cleanup(void)
static void close_one(struct ssl_connect_data *connssl)
{
/* before the cleanup, check whether we are using a client certificate */
- struct ssl_backend_data *backend = connssl->backend;
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
bool client_cert = true;
DEBUGASSERT(backend);
@@ -1580,7 +1590,8 @@ static void close_one(struct ssl_connect_data *connssl)
static void nss_close(struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
(void)data;
DEBUGASSERT(backend);
@@ -1796,7 +1807,8 @@ static CURLcode nss_fail_connect(struct Curl_cfilter *cf,
CURLcode curlerr)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
DEBUGASSERT(backend);
@@ -1826,7 +1838,8 @@ static CURLcode nss_set_blocking(struct Curl_cfilter *cf,
{
struct ssl_connect_data *connssl = cf->ctx;
PRSocketOptionData sock_opt;
- struct ssl_backend_data *backend = connssl->backend;
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
DEBUGASSERT(backend);
@@ -1849,7 +1862,8 @@ static CURLcode nss_setup_connect(struct Curl_cfilter *cf,
PRBool ssl_cbc_random_iv;
curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
struct Curl_cfilter *cf_ssl_next = Curl_ssl_cf_get_ssl(cf->next);
@@ -2031,14 +2045,16 @@ static CURLcode nss_setup_connect(struct Curl_cfilter *cf,
/* Is there an SSL filter "in front" of us or are we writing directly
* to the socket? */
if(connssl_next) {
+ struct nss_ssl_backend_data *backend_next =
+ (struct nss_ssl_backend_data *)connssl_next->backend;
/* The filter should be connected by now, with full handshake */
- DEBUGASSERT(connssl_next->backend->handle);
+ DEBUGASSERT(backend_next->handle);
DEBUGASSERT(ssl_connection_complete == connssl_next->state);
/* We tell our NSS instance to use do IO with the 'next' NSS
* instance. This NSS instance will take ownership of the next
* one, including its destruction. We therefore need to `disown`
* the next filter's handle, once import succeeds. */
- nspr_io = connssl_next->backend->handle;
+ nspr_io = backend->handle;
second_layer = TRUE;
}
else {
@@ -2077,8 +2093,11 @@ static CURLcode nss_setup_connect(struct Curl_cfilter *cf,
PR_Close(model); /* We don't need this any more */
model = NULL;
- if(connssl_next) /* steal the NSS handle we just imported successfully */
- connssl_next->backend->handle = NULL;
+ if(connssl_next) { /* steal the NSS handle we just imported successfully */
+ struct nss_ssl_backend_data *backend_next =
+ (struct nss_ssl_backend_data *)connssl_next->backend;
+ backend_next->handle = NULL;
+ }
/* This is the password associated with the cert that we're using */
if(ssl_config->key_passwd) {
@@ -2154,7 +2173,8 @@ static CURLcode nss_do_connect(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
CURLcode result = CURLE_SSL_CONNECT_ERROR;
@@ -2299,7 +2319,8 @@ static ssize_t nss_send(struct Curl_cfilter *cf,
CURLcode *curlcode)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
ssize_t rc;
(void)data;
@@ -2337,7 +2358,9 @@ static bool
nss_data_pending(struct Curl_cfilter *cf, const struct Curl_easy *data)
{
struct ssl_connect_data *connssl = cf->ctx;
- PRFileDesc *fd = connssl->backend->handle->lower;
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
+ PRFileDesc *fd = backend->handle->lower;
char buf;
(void) data;
@@ -2353,7 +2376,8 @@ static ssize_t nss_recv(struct Curl_cfilter *cf,
CURLcode *curlcode)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
ssize_t nread;
(void)data;
@@ -2455,7 +2479,8 @@ static bool nss_false_start(void)
static void *nss_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM)
{
- struct ssl_backend_data *backend = connssl->backend;
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
(void)info;
DEBUGASSERT(backend);
return backend->handle;
@@ -2465,9 +2490,11 @@ static bool nss_attach_data(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
struct ssl_connect_data *connssl = cf->ctx;
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
- if(!connssl->backend->data)
- connssl->backend->data = data;
+ if(!backend->data)
+ backend->data = data;
return TRUE;
}
@@ -2475,9 +2502,11 @@ static void nss_detach_data(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
struct ssl_connect_data *connssl = cf->ctx;
+ struct nss_ssl_backend_data *backend =
+ (struct nss_ssl_backend_data *)connssl->backend;
- if(connssl->backend->data == data)
- connssl->backend->data = NULL;
+ if(backend->data == data)
+ backend->data = NULL;
}
const struct Curl_ssl Curl_ssl_nss = {
@@ -2488,7 +2517,7 @@ const struct Curl_ssl Curl_ssl_nss = {
SSLSUPP_PINNEDPUBKEY |
SSLSUPP_HTTPS_PROXY,
- sizeof(struct ssl_backend_data),
+ sizeof(struct nss_ssl_backend_data),
nss_init, /* init */
nss_cleanup, /* cleanup */
diff --git a/Utilities/cmcurl/lib/vtls/openssl.c b/Utilities/cmcurl/lib/vtls/openssl.c
index 1c6c786..e6dd398 100644
--- a/Utilities/cmcurl/lib/vtls/openssl.c
+++ b/Utilities/cmcurl/lib/vtls/openssl.c
@@ -296,7 +296,7 @@ typedef unsigned long sslerr_t;
#define USE_PRE_1_1_API (OPENSSL_VERSION_NUMBER < 0x10100000L)
#endif /* !LIBRESSL_VERSION_NUMBER */
-struct ssl_backend_data {
+struct ossl_ssl_backend_data {
/* these ones requires specific SSL-types */
SSL_CTX* ctx;
SSL* handle;
@@ -722,6 +722,8 @@ static int bio_cf_out_write(BIO *bio, const char *buf, int blen)
{
struct Curl_cfilter *cf = BIO_get_data(bio);
struct ssl_connect_data *connssl = cf->ctx;
+ struct ossl_ssl_backend_data *backend =
+ (struct ossl_ssl_backend_data *)connssl->backend;
struct Curl_easy *data = CF_DATA_CURRENT(cf);
ssize_t nwritten;
CURLcode result = CURLE_SEND_ERROR;
@@ -731,7 +733,7 @@ static int bio_cf_out_write(BIO *bio, const char *buf, int blen)
DEBUGF(LOG_CF(data, cf, "bio_cf_out_write(len=%d) -> %d, err=%d",
blen, (int)nwritten, result));
BIO_clear_retry_flags(bio);
- connssl->backend->io_result = result;
+ backend->io_result = result;
if(nwritten < 0) {
if(CURLE_AGAIN == result)
BIO_set_retry_write(bio);
@@ -743,6 +745,8 @@ static int bio_cf_in_read(BIO *bio, char *buf, int blen)
{
struct Curl_cfilter *cf = BIO_get_data(bio);
struct ssl_connect_data *connssl = cf->ctx;
+ struct ossl_ssl_backend_data *backend =
+ (struct ossl_ssl_backend_data *)connssl->backend;
struct Curl_easy *data = CF_DATA_CURRENT(cf);
ssize_t nread;
CURLcode result = CURLE_RECV_ERROR;
@@ -756,7 +760,7 @@ static int bio_cf_in_read(BIO *bio, char *buf, int blen)
DEBUGF(LOG_CF(data, cf, "bio_cf_in_read(len=%d) -> %d, err=%d",
blen, (int)nread, result));
BIO_clear_retry_flags(bio);
- connssl->backend->io_result = result;
+ backend->io_result = result;
if(nread < 0) {
if(CURLE_AGAIN == result)
BIO_set_retry_read(bio);
@@ -764,13 +768,13 @@ static int bio_cf_in_read(BIO *bio, char *buf, int blen)
/* Before returning server replies to the SSL instance, we need
* to have setup the x509 store or verification will fail. */
- if(!connssl->backend->x509_store_setup) {
- result = Curl_ssl_setup_x509_store(cf, data, connssl->backend->ctx);
+ if(!backend->x509_store_setup) {
+ result = Curl_ssl_setup_x509_store(cf, data, backend->ctx);
if(result) {
- connssl->backend->io_result = result;
+ backend->io_result = result;
return -1;
}
- connssl->backend->x509_store_setup = TRUE;
+ backend->x509_store_setup = TRUE;
}
return (int)nread;
@@ -1885,7 +1889,8 @@ static struct curl_slist *ossl_engines_list(struct Curl_easy *data)
static void ossl_close(struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct ossl_ssl_backend_data *backend =
+ (struct ossl_ssl_backend_data *)connssl->backend;
(void)data;
DEBUGASSERT(backend);
@@ -1931,7 +1936,8 @@ static int ossl_shutdown(struct Curl_cfilter *cf,
int buffsize;
int err;
bool done = FALSE;
- struct ssl_backend_data *backend = connssl->backend;
+ struct ossl_ssl_backend_data *backend =
+ (struct ossl_ssl_backend_data *)connssl->backend;
int loop = 10;
DEBUGASSERT(backend);
@@ -2329,7 +2335,8 @@ static CURLcode verifystatus(struct Curl_cfilter *cf,
OCSP_BASICRESP *br = NULL;
X509_STORE *st = NULL;
STACK_OF(X509) *ch = NULL;
- struct ssl_backend_data *backend = connssl->backend;
+ struct ossl_ssl_backend_data *backend =
+ (struct ossl_ssl_backend_data *)connssl->backend;
X509 *cert;
OCSP_CERTID *id = NULL;
int cert_status, crl_reason;
@@ -2729,7 +2736,7 @@ static void ossl_trace(int direction, int ssl_ver, int content_type,
#ifdef HAS_MODERN_SET_PROTO_VER
static CURLcode
-set_ssl_version_min_max(struct Curl_cfilter *cf, SSL_CTX *ctx)
+ossl_set_ssl_version_min_max(struct Curl_cfilter *cf, SSL_CTX *ctx)
{
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
/* first, TLS min version... */
@@ -2826,9 +2833,9 @@ typedef long ctx_option_t;
#if !defined(HAS_MODERN_SET_PROTO_VER)
static CURLcode
-set_ssl_version_min_max_legacy(ctx_option_t *ctx_options,
- struct Curl_cfilter *cf,
- struct Curl_easy *data)
+ossl_set_ssl_version_min_max_legacy(ctx_option_t *ctx_options,
+ struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
long ssl_version = conn_config->version;
@@ -2841,8 +2848,10 @@ set_ssl_version_min_max_legacy(ctx_option_t *ctx_options,
#ifdef TLS1_3_VERSION
{
struct ssl_connect_data *connssl = cf->ctx;
- DEBUGASSERT(connssl->backend);
- SSL_CTX_set_max_proto_version(connssl->backend->ctx, TLS1_3_VERSION);
+ struct ossl_ssl_backend_data *backend =
+ (struct ossl_ssl_backend_data *)connssl->backend;
+ DEBUGASSERT(backend);
+ SSL_CTX_set_max_proto_version(backend->ctx, TLS1_3_VERSION);
*ctx_options |= SSL_OP_NO_TLSv1_2;
}
#else
@@ -3447,7 +3456,8 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
const char * const ssl_cert_type = ssl_config->cert_type;
const bool verifypeer = conn_config->verifypeer;
char error_buffer[256];
- struct ssl_backend_data *backend = connssl->backend;
+ struct ossl_ssl_backend_data *backend =
+ (struct ossl_ssl_backend_data *)connssl->backend;
DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
DEBUGASSERT(backend);
@@ -3589,9 +3599,9 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf,
ctx_options |= SSL_OP_NO_SSLv3;
#if HAS_MODERN_SET_PROTO_VER /* 1.1.0 */
- result = set_ssl_version_min_max(cf, backend->ctx);
+ result = ossl_set_ssl_version_min_max(cf, backend->ctx);
#else
- result = set_ssl_version_min_max_legacy(&ctx_options, cf, data);
+ result = ossl_set_ssl_version_min_max_legacy(&ctx_options, cf, data);
#endif
if(result != CURLE_OK)
return result;
@@ -3820,7 +3830,8 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
{
int err;
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct ossl_ssl_backend_data *backend =
+ (struct ossl_ssl_backend_data *)connssl->backend;
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
|| ssl_connect_2_reading == connssl->connecting_state
@@ -3983,8 +3994,8 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf,
* Heavily modified from:
* https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning#OpenSSL
*/
-static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, X509* cert,
- const char *pinnedpubkey)
+static CURLcode ossl_pkp_pin_peer_pubkey(struct Curl_easy *data, X509* cert,
+ const char *pinnedpubkey)
{
/* Scratch */
int len1 = 0, len2 = 0;
@@ -4062,7 +4073,8 @@ static CURLcode servercert(struct Curl_cfilter *cf,
char buffer[2048];
const char *ptr;
BIO *mem = BIO_new(BIO_s_mem());
- struct ssl_backend_data *backend = connssl->backend;
+ struct ossl_ssl_backend_data *backend =
+ (struct ossl_ssl_backend_data *)connssl->backend;
DEBUGASSERT(backend);
@@ -4077,7 +4089,7 @@ static CURLcode servercert(struct Curl_cfilter *cf,
if(data->set.ssl.certinfo)
/* asked to gather certificate info */
- (void)Curl_ossl_certchain(data, connssl->backend->handle);
+ (void)Curl_ossl_certchain(data, backend->handle);
backend->server_cert = SSL_get1_peer_certificate(backend->handle);
if(!backend->server_cert) {
@@ -4245,7 +4257,7 @@ static CURLcode servercert(struct Curl_cfilter *cf,
data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]:
data->set.str[STRING_SSL_PINNEDPUBLICKEY];
if(!result && ptr) {
- result = pkp_pin_peer_pubkey(data, backend->server_cert, ptr);
+ result = ossl_pkp_pin_peer_pubkey(data, backend->server_cert, ptr);
if(result)
failf(data, "SSL: public key does not match pinned public key");
}
@@ -4414,11 +4426,13 @@ static CURLcode ossl_connect(struct Curl_cfilter *cf,
static bool ossl_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data)
{
- struct ssl_connect_data *ctx = cf->ctx;
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct ossl_ssl_backend_data *backend =
+ (struct ossl_ssl_backend_data *)connssl->backend;
(void)data;
- DEBUGASSERT(ctx && ctx->backend);
- if(ctx->backend->handle && SSL_pending(ctx->backend->handle))
+ DEBUGASSERT(connssl && backend);
+ if(backend->handle && SSL_pending(backend->handle))
return TRUE;
return FALSE;
}
@@ -4437,7 +4451,8 @@ static ssize_t ossl_send(struct Curl_cfilter *cf,
int memlen;
int rc;
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct ossl_ssl_backend_data *backend =
+ (struct ossl_ssl_backend_data *)connssl->backend;
(void)data;
DEBUGASSERT(backend);
@@ -4533,7 +4548,8 @@ static ssize_t ossl_recv(struct Curl_cfilter *cf,
int buffsize;
struct connectdata *conn = cf->conn;
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct ossl_ssl_backend_data *backend =
+ (struct ossl_ssl_backend_data *)connssl->backend;
(void)data;
DEBUGASSERT(backend);
@@ -4756,7 +4772,8 @@ static void *ossl_get_internals(struct ssl_connect_data *connssl,
CURLINFO info)
{
/* Legacy: CURLINFO_TLS_SESSION must return an SSL_CTX pointer. */
- struct ssl_backend_data *backend = connssl->backend;
+ struct ossl_ssl_backend_data *backend =
+ (struct ossl_ssl_backend_data *)connssl->backend;
DEBUGASSERT(backend);
return info == CURLINFO_TLS_SESSION ?
(void *)backend->ctx : (void *)backend->handle;
@@ -4789,7 +4806,7 @@ const struct Curl_ssl Curl_ssl_openssl = {
#endif
SSLSUPP_HTTPS_PROXY,
- sizeof(struct ssl_backend_data),
+ sizeof(struct ossl_ssl_backend_data),
ossl_init, /* init */
ossl_cleanup, /* cleanup */
diff --git a/Utilities/cmcurl/lib/vtls/rustls.c b/Utilities/cmcurl/lib/vtls/rustls.c
index 097c58c..76d3e24 100644
--- a/Utilities/cmcurl/lib/vtls/rustls.c
+++ b/Utilities/cmcurl/lib/vtls/rustls.c
@@ -40,7 +40,7 @@
#include "strerror.h"
#include "multiif.h"
-struct ssl_backend_data
+struct rustls_ssl_backend_data
{
const struct rustls_client_config *config;
struct rustls_connection *conn;
@@ -67,10 +67,12 @@ static bool
cr_data_pending(struct Curl_cfilter *cf, const struct Curl_easy *data)
{
struct ssl_connect_data *ctx = cf->ctx;
+ struct rustls_ssl_backend_data *backend;
(void)data;
DEBUGASSERT(ctx && ctx->backend);
- return ctx->backend->data_pending;
+ backend = (struct rustls_ssl_backend_data *)ctx->backend;
+ return backend->data_pending;
}
static CURLcode
@@ -136,7 +138,8 @@ static ssize_t tls_recv_more(struct Curl_cfilter *cf,
struct Curl_easy *data, CURLcode *err)
{
struct ssl_connect_data *const connssl = cf->ctx;
- struct ssl_backend_data *const backend = connssl->backend;
+ struct rustls_ssl_backend_data *const backend =
+ (struct rustls_ssl_backend_data *)connssl->backend;
struct io_ctx io_ctx;
size_t tls_bytes_read = 0;
rustls_io_result io_error;
@@ -191,7 +194,8 @@ cr_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
char *plainbuf, size_t plainlen, CURLcode *err)
{
struct ssl_connect_data *const connssl = cf->ctx;
- struct ssl_backend_data *const backend = connssl->backend;
+ struct rustls_ssl_backend_data *const backend =
+ (struct rustls_ssl_backend_data *)connssl->backend;
struct rustls_connection *rconn = NULL;
size_t n = 0;
size_t plain_bytes_copied = 0;
@@ -283,7 +287,8 @@ cr_send(struct Curl_cfilter *cf, struct Curl_easy *data,
const void *plainbuf, size_t plainlen, CURLcode *err)
{
struct ssl_connect_data *const connssl = cf->ctx;
- struct ssl_backend_data *const backend = connssl->backend;
+ struct rustls_ssl_backend_data *const backend =
+ (struct rustls_ssl_backend_data *)connssl->backend;
struct rustls_connection *rconn = NULL;
struct io_ctx io_ctx;
size_t plainwritten = 0;
@@ -373,7 +378,7 @@ cr_hostname_is_ip(const char *hostname)
static CURLcode
cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data,
- struct ssl_backend_data *const backend)
+ struct rustls_ssl_backend_data *const backend)
{
struct ssl_connect_data *connssl = cf->ctx;
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
@@ -491,7 +496,8 @@ cr_connect_nonblocking(struct Curl_cfilter *cf,
{
struct ssl_connect_data *const connssl = cf->ctx;
curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
- struct ssl_backend_data *const backend = connssl->backend;
+ struct rustls_ssl_backend_data *const backend =
+ (struct rustls_ssl_backend_data *)connssl->backend;
struct rustls_connection *rconn = NULL;
CURLcode tmperr = CURLE_OK;
int result;
@@ -504,7 +510,8 @@ cr_connect_nonblocking(struct Curl_cfilter *cf,
DEBUGASSERT(backend);
if(ssl_connection_none == connssl->state) {
- result = cr_init_backend(cf, data, connssl->backend);
+ result = cr_init_backend(cf, data,
+ (struct rustls_ssl_backend_data *)connssl->backend);
if(result != CURLE_OK) {
return result;
}
@@ -594,7 +601,8 @@ cr_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data,
{
struct ssl_connect_data *const connssl = cf->ctx;
curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
- struct ssl_backend_data *const backend = connssl->backend;
+ struct rustls_ssl_backend_data *const backend =
+ (struct rustls_ssl_backend_data *)connssl->backend;
struct rustls_connection *rconn = NULL;
(void)data;
@@ -617,7 +625,8 @@ static void *
cr_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM)
{
- struct ssl_backend_data *backend = connssl->backend;
+ struct rustls_ssl_backend_data *backend =
+ (struct rustls_ssl_backend_data *)connssl->backend;
DEBUGASSERT(backend);
return &backend->conn;
}
@@ -626,7 +635,8 @@ static void
cr_close(struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct rustls_ssl_backend_data *backend =
+ (struct rustls_ssl_backend_data *)connssl->backend;
CURLcode tmperr = CURLE_OK;
ssize_t n = 0;
@@ -659,7 +669,7 @@ const struct Curl_ssl Curl_ssl_rustls = {
SSLSUPP_CAINFO_BLOB | /* supports */
SSLSUPP_TLS13_CIPHERSUITES |
SSLSUPP_HTTPS_PROXY,
- sizeof(struct ssl_backend_data),
+ sizeof(struct rustls_ssl_backend_data),
Curl_none_init, /* init */
Curl_none_cleanup, /* cleanup */
diff --git a/Utilities/cmcurl/lib/vtls/schannel.c b/Utilities/cmcurl/lib/vtls/schannel.c
index 513811d..5dcf5ba 100644
--- a/Utilities/cmcurl/lib/vtls/schannel.c
+++ b/Utilities/cmcurl/lib/vtls/schannel.c
@@ -33,13 +33,12 @@
#ifdef USE_SCHANNEL
-#define EXPOSE_SCHANNEL_INTERNAL_STRUCTS
-
#ifndef USE_WINDOWS_SSPI
# error "Can't compile SCHANNEL support without SSPI."
#endif
#include "schannel.h"
+#include "schannel_int.h"
#include "vtls.h"
#include "vtls_int.h"
#include "strcase.h"
@@ -186,9 +185,9 @@
#define PKCS12_NO_PERSIST_KEY 0x00008000
#endif
-static CURLcode pkp_pin_peer_pubkey(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- const char *pinnedpubkey);
+static CURLcode schannel_pkp_pin_peer_pubkey(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const char *pinnedpubkey);
static void InitSecBuffer(SecBuffer *buffer, unsigned long BufType,
void *BufDataPtr, unsigned long BufByteSize)
@@ -207,9 +206,9 @@ static void InitSecBufferDesc(SecBufferDesc *desc, SecBuffer *BufArr,
}
static CURLcode
-set_ssl_version_min_max(DWORD *enabled_protocols,
- struct Curl_cfilter *cf,
- struct Curl_easy *data)
+schannel_set_ssl_version_min_max(DWORD *enabled_protocols,
+ struct Curl_cfilter *cf,
+ struct Curl_easy *data)
{
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
long ssl_version = conn_config->version;
@@ -500,7 +499,8 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf,
DWORD flags = 0;
DWORD enabled_protocols = 0;
- struct ssl_backend_data *backend = connssl->backend;
+ struct schannel_ssl_backend_data *backend =
+ (struct schannel_ssl_backend_data *)(connssl->backend);
DEBUGASSERT(backend);
@@ -563,7 +563,7 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf,
case CURL_SSLVERSION_TLSv1_2:
case CURL_SSLVERSION_TLSv1_3:
{
- result = set_ssl_version_min_max(&enabled_protocols, cf, data);
+ result = schannel_set_ssl_version_min_max(&enabled_protocols, cf, data);
if(result != CURLE_OK)
return result;
break;
@@ -1075,7 +1075,8 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
{
ssize_t written = -1;
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct schannel_ssl_backend_data *backend =
+ (struct schannel_ssl_backend_data *)connssl->backend;
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
SecBuffer outbuf;
@@ -1349,7 +1350,8 @@ static CURLcode
schannel_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct schannel_ssl_backend_data *backend =
+ (struct schannel_ssl_backend_data *)connssl->backend;
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
int i;
ssize_t nread = -1, written = -1;
@@ -1607,7 +1609,7 @@ schannel_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]:
data->set.str[STRING_SSL_PINNEDPUBLICKEY];
if(pubkey_ptr) {
- result = pkp_pin_peer_pubkey(cf, data, pubkey_ptr);
+ result = schannel_pkp_pin_peer_pubkey(cf, data, pubkey_ptr);
if(result) {
failf(data, "SSL: public key does not match pinned public key");
return result;
@@ -1686,7 +1688,8 @@ static CURLcode
schannel_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct schannel_ssl_backend_data *backend =
+ (struct schannel_ssl_backend_data *)connssl->backend;
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
CURLcode result = CURLE_OK;
SECURITY_STATUS sspi_status = SEC_E_OK;
@@ -1931,7 +1934,8 @@ schannel_connect_common(struct Curl_cfilter *cf,
* Available on Windows 7 or later.
*/
{
- struct ssl_backend_data *backend = connssl->backend;
+ struct schannel_ssl_backend_data *backend =
+ (struct schannel_ssl_backend_data *)connssl->backend;
DEBUGASSERT(backend);
cf->conn->sslContext = &backend->ctxt->ctxt_handle;
}
@@ -1960,7 +1964,8 @@ schannel_send(struct Curl_cfilter *cf, struct Curl_easy *data,
SecBufferDesc outbuf_desc;
SECURITY_STATUS sspi_status = SEC_E_OK;
CURLcode result;
- struct ssl_backend_data *backend = connssl->backend;
+ struct schannel_ssl_backend_data *backend =
+ (struct schannel_ssl_backend_data *)connssl->backend;
DEBUGASSERT(backend);
@@ -2110,7 +2115,8 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
/* we want the length of the encrypted buffer to be at least large enough
that it can hold all the bytes requested and some TLS record overhead. */
size_t min_encdata_length = len + CURL_SCHANNEL_BUFFER_FREE_SIZE;
- struct ssl_backend_data *backend = connssl->backend;
+ struct schannel_ssl_backend_data *backend =
+ (struct schannel_ssl_backend_data *)connssl->backend;
DEBUGASSERT(backend);
@@ -2443,12 +2449,13 @@ static bool schannel_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data)
{
const struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct schannel_ssl_backend_data *backend =
+ (struct schannel_ssl_backend_data *)connssl->backend;
(void)data;
DEBUGASSERT(backend);
- if(connssl->backend->ctxt) /* SSL/TLS is in use */
+ if(backend->ctxt) /* SSL/TLS is in use */
return (backend->decdata_offset > 0 ||
(backend->encdata_offset > 0 && !backend->encdata_is_incomplete));
else
@@ -2486,12 +2493,13 @@ static int schannel_shutdown(struct Curl_cfilter *cf,
* Shutting Down an Schannel Connection
*/
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct schannel_ssl_backend_data *backend =
+ (struct schannel_ssl_backend_data *)connssl->backend;
DEBUGASSERT(data);
DEBUGASSERT(backend);
- if(connssl->backend->ctxt) {
+ if(backend->ctxt) {
infof(data, "schannel: shutting down SSL/TLS connection with %s port %d",
connssl->hostname, connssl->port);
}
@@ -2611,12 +2619,13 @@ static CURLcode schannel_random(struct Curl_easy *data UNUSED_PARAM,
return Curl_win32_random(entropy, length);
}
-static CURLcode pkp_pin_peer_pubkey(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- const char *pinnedpubkey)
+static CURLcode schannel_pkp_pin_peer_pubkey(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const char *pinnedpubkey)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct schannel_ssl_backend_data *backend =
+ (struct schannel_ssl_backend_data *)connssl->backend;
CERT_CONTEXT *pCertContextServer = NULL;
/* Result is returned to caller */
@@ -2742,7 +2751,8 @@ static CURLcode schannel_sha256sum(const unsigned char *input,
static void *schannel_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM)
{
- struct ssl_backend_data *backend = connssl->backend;
+ struct schannel_ssl_backend_data *backend =
+ (struct schannel_ssl_backend_data *)connssl->backend;
(void)info;
DEBUGASSERT(backend);
return &backend->ctxt->ctxt_handle;
@@ -2759,7 +2769,7 @@ const struct Curl_ssl Curl_ssl_schannel = {
SSLSUPP_TLS13_CIPHERSUITES |
SSLSUPP_HTTPS_PROXY,
- sizeof(struct ssl_backend_data),
+ sizeof(struct schannel_ssl_backend_data),
schannel_init, /* init */
schannel_cleanup, /* cleanup */
diff --git a/Utilities/cmcurl/lib/vtls/schannel.h b/Utilities/cmcurl/lib/vtls/schannel.h
index 7fae39f..b8cb494 100644
--- a/Utilities/cmcurl/lib/vtls/schannel.h
+++ b/Utilities/cmcurl/lib/vtls/schannel.h
@@ -28,8 +28,6 @@
#ifdef USE_SCHANNEL
-#define SCHANNEL_USE_BLACKLISTS 1
-
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4201)
@@ -81,119 +79,5 @@ extern const struct Curl_ssl Curl_ssl_schannel;
CURLcode Curl_verify_certificate(struct Curl_cfilter *cf,
struct Curl_easy *data);
-/* structs to expose only in schannel.c and schannel_verify.c */
-#ifdef EXPOSE_SCHANNEL_INTERNAL_STRUCTS
-
-#ifdef __MINGW32__
-#ifdef __MINGW64_VERSION_MAJOR
-#define HAS_MANUAL_VERIFY_API
-#endif
-#else
-#ifdef CERT_CHAIN_REVOCATION_CHECK_CHAIN
-#define HAS_MANUAL_VERIFY_API
-#endif
-#endif
-
-#if defined(CryptStringToBinary) && defined(CRYPT_STRING_HEX) \
- && !defined(DISABLE_SCHANNEL_CLIENT_CERT)
-#define HAS_CLIENT_CERT_PATH
-#endif
-
-#ifndef SCH_CREDENTIALS_VERSION
-
-#define SCH_CREDENTIALS_VERSION 0x00000005
-
-typedef enum _eTlsAlgorithmUsage
-{
- TlsParametersCngAlgUsageKeyExchange,
- TlsParametersCngAlgUsageSignature,
- TlsParametersCngAlgUsageCipher,
- TlsParametersCngAlgUsageDigest,
- TlsParametersCngAlgUsageCertSig
-} eTlsAlgorithmUsage;
-
-typedef struct _CRYPTO_SETTINGS
-{
- eTlsAlgorithmUsage eAlgorithmUsage;
- UNICODE_STRING strCngAlgId;
- DWORD cChainingModes;
- PUNICODE_STRING rgstrChainingModes;
- DWORD dwMinBitLength;
- DWORD dwMaxBitLength;
-} CRYPTO_SETTINGS, * PCRYPTO_SETTINGS;
-
-typedef struct _TLS_PARAMETERS
-{
- DWORD cAlpnIds;
- PUNICODE_STRING rgstrAlpnIds;
- DWORD grbitDisabledProtocols;
- DWORD cDisabledCrypto;
- PCRYPTO_SETTINGS pDisabledCrypto;
- DWORD dwFlags;
-} TLS_PARAMETERS, * PTLS_PARAMETERS;
-
-typedef struct _SCH_CREDENTIALS
-{
- DWORD dwVersion;
- DWORD dwCredFormat;
- DWORD cCreds;
- PCCERT_CONTEXT* paCred;
- HCERTSTORE hRootStore;
-
- DWORD cMappers;
- struct _HMAPPER **aphMappers;
-
- DWORD dwSessionLifespan;
- DWORD dwFlags;
- DWORD cTlsParameters;
- PTLS_PARAMETERS pTlsParameters;
-} SCH_CREDENTIALS, * PSCH_CREDENTIALS;
-
-#define SCH_CRED_MAX_SUPPORTED_PARAMETERS 16
-#define SCH_CRED_MAX_SUPPORTED_ALPN_IDS 16
-#define SCH_CRED_MAX_SUPPORTED_CRYPTO_SETTINGS 16
-#define SCH_CRED_MAX_SUPPORTED_CHAINING_MODES 16
-
-#endif
-
-struct Curl_schannel_cred {
- CredHandle cred_handle;
- TimeStamp time_stamp;
- TCHAR *sni_hostname;
-#ifdef HAS_CLIENT_CERT_PATH
- HCERTSTORE client_cert_store;
-#endif
- int refcount;
-};
-
-struct Curl_schannel_ctxt {
- CtxtHandle ctxt_handle;
- TimeStamp time_stamp;
-};
-
-struct ssl_backend_data {
- struct Curl_schannel_cred *cred;
- struct Curl_schannel_ctxt *ctxt;
- SecPkgContext_StreamSizes stream_sizes;
- size_t encdata_length, decdata_length;
- size_t encdata_offset, decdata_offset;
- unsigned char *encdata_buffer, *decdata_buffer;
- /* encdata_is_incomplete: if encdata contains only a partial record that
- can't be decrypted without another recv() (that is, status is
- SEC_E_INCOMPLETE_MESSAGE) then set this true. after an recv() adds
- more bytes into encdata then set this back to false. */
- bool encdata_is_incomplete;
- unsigned long req_flags, ret_flags;
- CURLcode recv_unrecoverable_err; /* schannel_recv had an unrecoverable err */
- bool recv_sspi_close_notify; /* true if connection closed by close_notify */
- bool recv_connection_closed; /* true if connection closed, regardless how */
- bool recv_renegotiating; /* true if recv is doing renegotiation */
- bool use_alpn; /* true if ALPN is used for this connection */
-#ifdef HAS_MANUAL_VERIFY_API
- bool use_manual_cred_validation; /* true if manual cred validation is used */
-#endif
-};
-#endif /* EXPOSE_SCHANNEL_INTERNAL_STRUCTS */
-
#endif /* USE_SCHANNEL */
#endif /* HEADER_CURL_SCHANNEL_H */
diff --git a/Utilities/cmcurl/lib/vtls/schannel_int.h b/Utilities/cmcurl/lib/vtls/schannel_int.h
new file mode 100644
index 0000000..d8b6cce
--- /dev/null
+++ b/Utilities/cmcurl/lib/vtls/schannel_int.h
@@ -0,0 +1,142 @@
+#ifndef HEADER_CURL_SCHANNEL_INT_H
+#define HEADER_CURL_SCHANNEL_INT_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Marc Hoersken, <info@marc-hoersken.de>, et al.
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#ifdef USE_SCHANNEL
+
+#ifdef __MINGW32__
+#ifdef __MINGW64_VERSION_MAJOR
+#define HAS_MANUAL_VERIFY_API
+#endif
+#else
+#ifdef CERT_CHAIN_REVOCATION_CHECK_CHAIN
+#define HAS_MANUAL_VERIFY_API
+#endif
+#endif
+
+#if defined(CryptStringToBinary) && defined(CRYPT_STRING_HEX) \
+ && !defined(DISABLE_SCHANNEL_CLIENT_CERT)
+#define HAS_CLIENT_CERT_PATH
+#endif
+
+#ifndef SCH_CREDENTIALS_VERSION
+
+#define SCH_CREDENTIALS_VERSION 0x00000005
+
+typedef enum _eTlsAlgorithmUsage
+{
+ TlsParametersCngAlgUsageKeyExchange,
+ TlsParametersCngAlgUsageSignature,
+ TlsParametersCngAlgUsageCipher,
+ TlsParametersCngAlgUsageDigest,
+ TlsParametersCngAlgUsageCertSig
+} eTlsAlgorithmUsage;
+
+typedef struct _CRYPTO_SETTINGS
+{
+ eTlsAlgorithmUsage eAlgorithmUsage;
+ UNICODE_STRING strCngAlgId;
+ DWORD cChainingModes;
+ PUNICODE_STRING rgstrChainingModes;
+ DWORD dwMinBitLength;
+ DWORD dwMaxBitLength;
+} CRYPTO_SETTINGS, * PCRYPTO_SETTINGS;
+
+typedef struct _TLS_PARAMETERS
+{
+ DWORD cAlpnIds;
+ PUNICODE_STRING rgstrAlpnIds;
+ DWORD grbitDisabledProtocols;
+ DWORD cDisabledCrypto;
+ PCRYPTO_SETTINGS pDisabledCrypto;
+ DWORD dwFlags;
+} TLS_PARAMETERS, * PTLS_PARAMETERS;
+
+typedef struct _SCH_CREDENTIALS
+{
+ DWORD dwVersion;
+ DWORD dwCredFormat;
+ DWORD cCreds;
+ PCCERT_CONTEXT* paCred;
+ HCERTSTORE hRootStore;
+
+ DWORD cMappers;
+ struct _HMAPPER **aphMappers;
+
+ DWORD dwSessionLifespan;
+ DWORD dwFlags;
+ DWORD cTlsParameters;
+ PTLS_PARAMETERS pTlsParameters;
+} SCH_CREDENTIALS, * PSCH_CREDENTIALS;
+
+#define SCH_CRED_MAX_SUPPORTED_PARAMETERS 16
+#define SCH_CRED_MAX_SUPPORTED_ALPN_IDS 16
+#define SCH_CRED_MAX_SUPPORTED_CRYPTO_SETTINGS 16
+#define SCH_CRED_MAX_SUPPORTED_CHAINING_MODES 16
+
+#endif /* SCH_CREDENTIALS_VERSION */
+
+struct Curl_schannel_cred {
+ CredHandle cred_handle;
+ TimeStamp time_stamp;
+ TCHAR *sni_hostname;
+#ifdef HAS_CLIENT_CERT_PATH
+ HCERTSTORE client_cert_store;
+#endif
+ int refcount;
+};
+
+struct Curl_schannel_ctxt {
+ CtxtHandle ctxt_handle;
+ TimeStamp time_stamp;
+};
+
+struct schannel_ssl_backend_data {
+ struct Curl_schannel_cred *cred;
+ struct Curl_schannel_ctxt *ctxt;
+ SecPkgContext_StreamSizes stream_sizes;
+ size_t encdata_length, decdata_length;
+ size_t encdata_offset, decdata_offset;
+ unsigned char *encdata_buffer, *decdata_buffer;
+ /* encdata_is_incomplete: if encdata contains only a partial record that
+ can't be decrypted without another recv() (that is, status is
+ SEC_E_INCOMPLETE_MESSAGE) then set this true. after an recv() adds
+ more bytes into encdata then set this back to false. */
+ bool encdata_is_incomplete;
+ unsigned long req_flags, ret_flags;
+ CURLcode recv_unrecoverable_err; /* schannel_recv had an unrecoverable err */
+ bool recv_sspi_close_notify; /* true if connection closed by close_notify */
+ bool recv_connection_closed; /* true if connection closed, regardless how */
+ bool recv_renegotiating; /* true if recv is doing renegotiation */
+ bool use_alpn; /* true if ALPN is used for this connection */
+#ifdef HAS_MANUAL_VERIFY_API
+ bool use_manual_cred_validation; /* true if manual cred validation is used */
+#endif
+};
+
+#endif /* USE_SCHANNEL */
+#endif /* HEADER_CURL_SCHANNEL_INT_H */
diff --git a/Utilities/cmcurl/lib/vtls/schannel_verify.c b/Utilities/cmcurl/lib/vtls/schannel_verify.c
index d75ee8d..c582ee4 100644
--- a/Utilities/cmcurl/lib/vtls/schannel_verify.c
+++ b/Utilities/cmcurl/lib/vtls/schannel_verify.c
@@ -36,8 +36,8 @@
# error "Can't compile SCHANNEL support without SSPI."
#endif
-#define EXPOSE_SCHANNEL_INTERNAL_STRUCTS
#include "schannel.h"
+#include "schannel_int.h"
#ifdef HAS_MANUAL_VERIFY_API
@@ -54,7 +54,7 @@
#include "curl_memory.h"
#include "memdebug.h"
-#define BACKEND connssl->backend
+#define BACKEND ((struct schannel_ssl_backend_data *)connssl->backend)
#define MAX_CAFILE_SIZE 1048576 /* 1 MiB */
#define BEGIN_CERT "-----BEGIN CERTIFICATE-----"
diff --git a/Utilities/cmcurl/lib/vtls/sectransp.c b/Utilities/cmcurl/lib/vtls/sectransp.c
index c9f02f2..32bb3a5 100644
--- a/Utilities/cmcurl/lib/vtls/sectransp.c
+++ b/Utilities/cmcurl/lib/vtls/sectransp.c
@@ -146,7 +146,7 @@
#define ioErr -36
#define paramErr -50
-struct ssl_backend_data {
+struct st_ssl_backend_data {
SSLContextRef ssl_ctx;
bool ssl_direction; /* true if writing, false if reading */
size_t ssl_write_buffered_length;
@@ -836,7 +836,8 @@ static OSStatus bio_cf_in_read(SSLConnectionRef connection,
{
struct Curl_cfilter *cf = (struct Curl_cfilter *)connection;
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct st_ssl_backend_data *backend =
+ (struct st_ssl_backend_data *)connssl->backend;
struct Curl_easy *data = CF_DATA_CURRENT(cf);
ssize_t nread;
CURLcode result;
@@ -859,6 +860,9 @@ static OSStatus bio_cf_in_read(SSLConnectionRef connection,
}
nread = 0;
}
+ else if(nread == 0) {
+ rtn = errSSLClosedGraceful;
+ }
else if((size_t)nread < *dataLength) {
rtn = errSSLWouldBlock;
}
@@ -872,7 +876,8 @@ static OSStatus bio_cf_out_write(SSLConnectionRef connection,
{
struct Curl_cfilter *cf = (struct Curl_cfilter *)connection;
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct st_ssl_backend_data *backend =
+ (struct st_ssl_backend_data *)connssl->backend;
struct Curl_easy *data = CF_DATA_CURRENT(cf);
ssize_t nwritten;
CURLcode result;
@@ -1338,7 +1343,8 @@ static CURLcode set_ssl_version_min_max(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct st_ssl_backend_data *backend =
+ (struct st_ssl_backend_data *)connssl->backend;
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
long ssl_version = conn_config->version;
long ssl_version_max = conn_config->version_max;
@@ -1633,7 +1639,8 @@ static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct st_ssl_backend_data *backend =
+ (struct st_ssl_backend_data *)connssl->backend;
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
const struct curl_blob *ssl_cablob = conn_config->ca_info_blob;
@@ -2515,7 +2522,8 @@ static CURLcode sectransp_connect_step2(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct st_ssl_backend_data *backend =
+ (struct st_ssl_backend_data *)connssl->backend;
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
OSStatus err;
SSLCipherSuite cipher;
@@ -2896,7 +2904,8 @@ static CURLcode collect_server_cert(struct Curl_cfilter *cf,
CURLcode result = ssl_config->certinfo ?
CURLE_PEER_FAILED_VERIFICATION : CURLE_OK;
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct st_ssl_backend_data *backend =
+ (struct st_ssl_backend_data *)connssl->backend;
CFArrayRef server_certs = NULL;
SecCertificateRef server_cert;
OSStatus err;
@@ -3139,7 +3148,8 @@ static CURLcode sectransp_connect(struct Curl_cfilter *cf,
static void sectransp_close(struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct st_ssl_backend_data *backend =
+ (struct st_ssl_backend_data *)connssl->backend;
(void) data;
@@ -3166,7 +3176,8 @@ static int sectransp_shutdown(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct st_ssl_backend_data *backend =
+ (struct st_ssl_backend_data *)connssl->backend;
ssize_t nread;
int what;
int rc;
@@ -3244,7 +3255,8 @@ static bool sectransp_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data)
{
const struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct st_ssl_backend_data *backend =
+ (struct st_ssl_backend_data *)connssl->backend;
OSStatus err;
size_t buffer;
@@ -3308,7 +3320,8 @@ static ssize_t sectransp_send(struct Curl_cfilter *cf,
CURLcode *curlcode)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct st_ssl_backend_data *backend =
+ (struct st_ssl_backend_data *)connssl->backend;
size_t processed = 0UL;
OSStatus err;
@@ -3376,7 +3389,8 @@ static ssize_t sectransp_recv(struct Curl_cfilter *cf,
CURLcode *curlcode)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct st_ssl_backend_data *backend =
+ (struct st_ssl_backend_data *)connssl->backend;
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
size_t processed = 0UL;
OSStatus err;
@@ -3434,7 +3448,8 @@ again:
static void *sectransp_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM)
{
- struct ssl_backend_data *backend = connssl->backend;
+ struct st_ssl_backend_data *backend =
+ (struct st_ssl_backend_data *)connssl->backend;
(void)info;
DEBUGASSERT(backend);
return backend->ssl_ctx;
@@ -3450,7 +3465,7 @@ const struct Curl_ssl Curl_ssl_sectransp = {
#endif /* SECTRANSP_PINNEDPUBKEY */
SSLSUPP_HTTPS_PROXY,
- sizeof(struct ssl_backend_data),
+ sizeof(struct st_ssl_backend_data),
Curl_none_init, /* init */
Curl_none_cleanup, /* cleanup */
diff --git a/Utilities/cmcurl/lib/vtls/vtls.c b/Utilities/cmcurl/lib/vtls/vtls.c
index a4ff7d6..510bcfe 100644
--- a/Utilities/cmcurl/lib/vtls/vtls.c
+++ b/Utilities/cmcurl/lib/vtls/vtls.c
@@ -453,7 +453,7 @@ bool Curl_ssl_getsessionid(struct Curl_cfilter *cf,
}
}
- DEBUGF(infof(data, DMSG(data, "%s Session ID in cache for %s %s://%s:%d"),
+ DEBUGF(infof(data, "%s Session ID in cache for %s %s://%s:%d",
no_match? "Didn't find": "Found",
Curl_ssl_cf_is_proxy(cf) ? "proxy" : "host",
cf->conn->handler->scheme, connssl->hostname, connssl->port));
@@ -601,8 +601,8 @@ CURLcode Curl_ssl_addsessionid(struct Curl_cfilter *cf,
if(added)
*added = TRUE;
- DEBUGF(infof(data, DMSG(data, "Added Session ID to cache for %s://%s:%d"
- " [%s]"), store->scheme, store->name, store->remote_port,
+ DEBUGF(infof(data, "Added Session ID to cache for %s://%s:%d [%s]",
+ store->scheme, store->name, store->remote_port,
Curl_ssl_cf_is_proxy(cf) ? "PROXY" : "server"));
return CURLE_OK;
}
@@ -893,8 +893,8 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
/* only do this if pinnedpubkey starts with "sha256//", length 8 */
if(strncmp(pinnedpubkey, "sha256//", 8) == 0) {
CURLcode encode;
- size_t encodedlen, pinkeylen;
- char *encoded, *pinkeycopy, *begin_pos, *end_pos;
+ size_t encodedlen = 0, pinkeylen;
+ char *encoded = NULL, *pinkeycopy, *begin_pos, *end_pos;
unsigned char *sha256sumdigest;
if(!Curl_ssl->sha256sum) {
@@ -907,14 +907,12 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
if(!sha256sumdigest)
return CURLE_OUT_OF_MEMORY;
encode = Curl_ssl->sha256sum(pubkey, pubkeylen,
- sha256sumdigest, CURL_SHA256_DIGEST_LENGTH);
+ sha256sumdigest, CURL_SHA256_DIGEST_LENGTH);
- if(encode != CURLE_OK)
- return encode;
-
- encode = Curl_base64_encode((char *)sha256sumdigest,
- CURL_SHA256_DIGEST_LENGTH, &encoded,
- &encodedlen);
+ if(!encode)
+ encode = Curl_base64_encode((char *)sha256sumdigest,
+ CURL_SHA256_DIGEST_LENGTH, &encoded,
+ &encodedlen);
Curl_safefree(sha256sumdigest);
if(encode)
@@ -1506,7 +1504,7 @@ static void ssl_cf_close(struct Curl_cfilter *cf,
CF_DATA_SAVE(save, cf, data);
cf_close(cf, data);
- cf->next->cft->close(cf->next, data);
+ cf->next->cft->do_close(cf->next, data);
CF_DATA_RESTORE(cf, save);
}
@@ -1530,7 +1528,7 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
DEBUGASSERT(connssl);
DEBUGASSERT(cf->conn->host.name);
- result = cf->next->cft->connect(cf->next, data, blocking, done);
+ result = cf->next->cft->do_connect(cf->next, data, blocking, done);
if(result || !*done)
goto out;
@@ -1594,6 +1592,7 @@ static ssize_t ssl_cf_recv(struct Curl_cfilter *cf,
ssize_t nread;
CF_DATA_SAVE(save, cf, data);
+ *err = CURLE_OK;
nread = Curl_ssl->recv_plain(cf, data, buf, len, err);
if(nread > 0) {
DEBUGASSERT((size_t)nread <= len);
diff --git a/Utilities/cmcurl/lib/vtls/vtls_int.h b/Utilities/cmcurl/lib/vtls/vtls_int.h
index ed49339..fe0115c 100644
--- a/Utilities/cmcurl/lib/vtls/vtls_int.h
+++ b/Utilities/cmcurl/lib/vtls/vtls_int.h
@@ -73,7 +73,7 @@ struct ssl_connect_data {
char *hostname; /* hostname for verification */
char *dispname; /* display version of hostname */
const struct alpn_spec *alpn; /* ALPN to use or NULL for none */
- struct ssl_backend_data *backend; /* vtls backend specific props */
+ void *backend; /* vtls backend specific props */
struct cf_call_data call_data; /* data handle used in current call */
struct curltime handshake_done; /* time when handshake finished */
int port; /* remote port at origin */
@@ -81,6 +81,7 @@ struct ssl_connect_data {
};
+#undef CF_CTX_CALL_DATA
#define CF_CTX_CALL_DATA(cf) \
((struct ssl_connect_data *)(cf)->ctx)->call_data
diff --git a/Utilities/cmcurl/lib/vtls/wolfssl.c b/Utilities/cmcurl/lib/vtls/wolfssl.c
index 2928728..6cfc201 100644
--- a/Utilities/cmcurl/lib/vtls/wolfssl.c
+++ b/Utilities/cmcurl/lib/vtls/wolfssl.c
@@ -91,7 +91,7 @@
#undef USE_BIO_CHAIN
#endif
-struct ssl_backend_data {
+struct wolfssl_ssl_backend_data {
SSL_CTX* ctx;
SSL* handle;
CURLcode io_result; /* result of last BIO cfilter operation */
@@ -281,13 +281,15 @@ static int bio_cf_out_write(WOLFSSL_BIO *bio, const char *buf, int blen)
{
struct Curl_cfilter *cf = wolfSSL_BIO_get_data(bio);
struct ssl_connect_data *connssl = cf->ctx;
+ struct wolfssl_ssl_backend_data *backend =
+ (struct wolfssl_ssl_backend_data *)connssl->backend;
struct Curl_easy *data = CF_DATA_CURRENT(cf);
ssize_t nwritten;
CURLcode result = CURLE_OK;
DEBUGASSERT(data);
nwritten = Curl_conn_cf_send(cf->next, data, buf, blen, &result);
- connssl->backend->io_result = result;
+ backend->io_result = result;
DEBUGF(LOG_CF(data, cf, "bio_write(len=%d) -> %zd, %d",
blen, nwritten, result));
wolfSSL_BIO_clear_retry_flags(bio);
@@ -300,6 +302,8 @@ static int bio_cf_in_read(WOLFSSL_BIO *bio, char *buf, int blen)
{
struct Curl_cfilter *cf = wolfSSL_BIO_get_data(bio);
struct ssl_connect_data *connssl = cf->ctx;
+ struct wolfssl_ssl_backend_data *backend =
+ (struct wolfssl_ssl_backend_data *)connssl->backend;
struct Curl_easy *data = CF_DATA_CURRENT(cf);
ssize_t nread;
CURLcode result = CURLE_OK;
@@ -310,7 +314,7 @@ static int bio_cf_in_read(WOLFSSL_BIO *bio, char *buf, int blen)
return 0;
nread = Curl_conn_cf_recv(cf->next, data, buf, blen, &result);
- connssl->backend->io_result = result;
+ backend->io_result = result;
DEBUGF(LOG_CF(data, cf, "bio_read(len=%d) -> %zd, %d",
blen, nread, result));
wolfSSL_BIO_clear_retry_flags(bio);
@@ -352,8 +356,10 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
{
char *ciphers, *curves;
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct wolfssl_ssl_backend_data *backend =
+ (struct wolfssl_ssl_backend_data *)connssl->backend;
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+ const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
const struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
SSL_METHOD* req_method = NULL;
#ifdef HAVE_LIBOQS
@@ -366,6 +372,7 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
#else
#define use_sni(x) Curl_nop_stmt
#endif
+ bool imported_ca_info_blob = false;
DEBUGASSERT(backend);
@@ -410,8 +417,13 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
#endif
break;
case CURL_SSLVERSION_TLSv1_2:
+#ifndef WOLFSSL_NO_TLS12
req_method = TLSv1_2_client_method();
use_sni(TRUE);
+#else
+ failf(data, "wolfSSL does not support TLS 1.2");
+ return CURLE_NOT_BUILT_IN;
+#endif
break;
case CURL_SSLVERSION_TLSv1_3:
#ifdef WOLFSSL_TLS13
@@ -494,13 +506,28 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
}
}
}
+
+ if(ca_info_blob) {
+ if(wolfSSL_CTX_load_verify_buffer(
+ backend->ctx, ca_info_blob->data, ca_info_blob->len,
+ SSL_FILETYPE_PEM
+ ) != SSL_SUCCESS) {
+ failf(data, "error importing CA certificate blob");
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ else {
+ imported_ca_info_blob = true;
+ infof(data, "successfully imported CA certificate blob");
+ }
+ }
+
#ifndef NO_FILESYSTEM
/* load trusted cacert */
if(conn_config->CAfile) {
if(1 != SSL_CTX_load_verify_locations(backend->ctx,
conn_config->CAfile,
conn_config->CApath)) {
- if(conn_config->verifypeer) {
+ if(conn_config->verifypeer && !imported_ca_info_blob) {
/* Fail if we insist on successfully verifying the server. */
failf(data, "error setting certificate verify locations:"
" CAfile: %s CApath: %s",
@@ -699,7 +726,8 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
{
int ret = -1;
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct wolfssl_ssl_backend_data *backend =
+ (struct wolfssl_ssl_backend_data *)connssl->backend;
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
const char * const pinnedpubkey = Curl_ssl_cf_is_proxy(cf)?
data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]:
@@ -892,7 +920,8 @@ wolfssl_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct wolfssl_ssl_backend_data *backend =
+ (struct wolfssl_ssl_backend_data *)connssl->backend;
const struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
@@ -950,7 +979,8 @@ static ssize_t wolfssl_send(struct Curl_cfilter *cf,
CURLcode *curlcode)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct wolfssl_ssl_backend_data *backend =
+ (struct wolfssl_ssl_backend_data *)connssl->backend;
char error_buffer[WOLFSSL_MAX_ERROR_SZ];
int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
int rc;
@@ -992,7 +1022,8 @@ static ssize_t wolfssl_send(struct Curl_cfilter *cf,
static void wolfssl_close(struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct wolfssl_ssl_backend_data *backend =
+ (struct wolfssl_ssl_backend_data *)connssl->backend;
(void) data;
@@ -1019,7 +1050,8 @@ static ssize_t wolfssl_recv(struct Curl_cfilter *cf,
CURLcode *curlcode)
{
struct ssl_connect_data *connssl = cf->ctx;
- struct ssl_backend_data *backend = connssl->backend;
+ struct wolfssl_ssl_backend_data *backend =
+ (struct wolfssl_ssl_backend_data *)connssl->backend;
char error_buffer[WOLFSSL_MAX_ERROR_SZ];
int buffsize = (blen > (size_t)INT_MAX) ? INT_MAX : (int)blen;
int nread;
@@ -1108,11 +1140,14 @@ static bool wolfssl_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data)
{
struct ssl_connect_data *ctx = cf->ctx;
+ struct wolfssl_ssl_backend_data *backend;
(void)data;
DEBUGASSERT(ctx && ctx->backend);
- if(ctx->backend->handle) /* SSL is in use */
- return (0 != SSL_pending(ctx->backend->handle)) ? TRUE : FALSE;
+
+ backend = (struct wolfssl_ssl_backend_data *)ctx->backend;
+ if(backend->handle) /* SSL is in use */
+ return (0 != SSL_pending(backend->handle)) ? TRUE : FALSE;
else
return FALSE;
}
@@ -1126,15 +1161,17 @@ static int wolfssl_shutdown(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
struct ssl_connect_data *ctx = cf->ctx;
+ struct wolfssl_ssl_backend_data *backend;
int retval = 0;
(void)data;
DEBUGASSERT(ctx && ctx->backend);
- if(ctx->backend->handle) {
+ backend = (struct wolfssl_ssl_backend_data *)ctx->backend;
+ if(backend->handle) {
ERR_clear_error();
- SSL_free(ctx->backend->handle);
- ctx->backend->handle = NULL;
+ SSL_free(backend->handle);
+ backend->handle = NULL;
}
return retval;
}
@@ -1305,7 +1342,8 @@ static CURLcode wolfssl_sha256sum(const unsigned char *tmp, /* input */
static void *wolfssl_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM)
{
- struct ssl_backend_data *backend = connssl->backend;
+ struct wolfssl_ssl_backend_data *backend =
+ (struct wolfssl_ssl_backend_data *)connssl->backend;
(void)info;
DEBUGASSERT(backend);
return backend->handle;
@@ -1320,9 +1358,10 @@ const struct Curl_ssl Curl_ssl_wolfssl = {
#ifdef USE_BIO_CHAIN
SSLSUPP_HTTPS_PROXY |
#endif
+ SSLSUPP_CAINFO_BLOB |
SSLSUPP_SSL_CTX,
- sizeof(struct ssl_backend_data),
+ sizeof(struct wolfssl_ssl_backend_data),
wolfssl_init, /* init */
wolfssl_cleanup, /* cleanup */
diff --git a/Utilities/cmcurl/lib/warnless.c b/Utilities/cmcurl/lib/warnless.c
index 10c91fb..65c5ec5 100644
--- a/Utilities/cmcurl/lib/warnless.c
+++ b/Utilities/cmcurl/lib/warnless.c
@@ -35,10 +35,13 @@
#endif /* __INTEL_COMPILER && __unix__ */
-#define BUILDING_WARNLESS_C 1
-
#include "warnless.h"
+#ifdef WIN32
+#undef read
+#undef write
+#endif
+
#include <limits.h>
#define CURL_MASK_UCHAR ((unsigned char)~0)
@@ -376,6 +379,9 @@ ssize_t curlx_write(int fd, const void *buf, size_t count)
return (ssize_t)write(fd, buf, curlx_uztoui(count));
}
+/* Ensure that warnless.h continues to have an effect in "unity" builds. */
+#undef HEADER_CURL_WARNLESS_H
+
#endif /* WIN32 */
#if defined(__INTEL_COMPILER) && defined(__unix__)
diff --git a/Utilities/cmcurl/lib/warnless.h b/Utilities/cmcurl/lib/warnless.h
index 99b2433..2a53016 100644
--- a/Utilities/cmcurl/lib/warnless.h
+++ b/Utilities/cmcurl/lib/warnless.h
@@ -75,12 +75,10 @@ ssize_t curlx_read(int fd, void *buf, size_t count);
ssize_t curlx_write(int fd, const void *buf, size_t count);
-#ifndef BUILDING_WARNLESS_C
-# undef read
-# define read(fd, buf, count) curlx_read(fd, buf, count)
-# undef write
-# define write(fd, buf, count) curlx_write(fd, buf, count)
-#endif
+#undef read
+#define read(fd, buf, count) curlx_read(fd, buf, count)
+#undef write
+#define write(fd, buf, count) curlx_write(fd, buf, count)
#endif /* WIN32 */
diff --git a/Utilities/cmcurl/lib/ws.c b/Utilities/cmcurl/lib/ws.c
index c60bbc9..3c1964b 100644
--- a/Utilities/cmcurl/lib/ws.c
+++ b/Utilities/cmcurl/lib/ws.c
@@ -126,8 +126,9 @@ static void ws_dec_info(struct ws_decoder *dec, struct Curl_easy *data,
dec->head_len, dec->head_total);
}
else {
- infof(data, "WS-DEC: %s [%s%s payload=%zd/%zd]", msg,
- ws_frame_name_of_op(dec->head[0]),
+ infof(data, "WS-DEC: %s [%s%s payload=%" CURL_FORMAT_CURL_OFF_T
+ "/%" CURL_FORMAT_CURL_OFF_T "]",
+ msg, ws_frame_name_of_op(dec->head[0]),
(dec->head[0] & WSBIT_FIN)? "" : " NON-FINAL",
dec->payload_offset, dec->payload_len);
}
@@ -272,7 +273,8 @@ static CURLcode ws_dec_pass_payload(struct ws_decoder *dec,
Curl_bufq_skip(inraw, (size_t)nwritten);
dec->payload_offset += (curl_off_t)nwritten;
remain = dec->payload_len - dec->payload_offset;
- /* infof(data, "WS-DEC: passed %zd bytes payload, %zd remain",
+ /* infof(data, "WS-DEC: passed %zd bytes payload, %"
+ CURL_FORMAT_CURL_OFF_T " remain",
nwritten, remain); */
}
@@ -351,8 +353,9 @@ static void update_meta(struct websocket *ws,
static void ws_enc_info(struct ws_encoder *enc, struct Curl_easy *data,
const char *msg)
{
- infof(data, "WS-ENC: %s [%s%s%s payload=%zd/%zd]", msg,
- ws_frame_name_of_op(enc->firstbyte),
+ infof(data, "WS-ENC: %s [%s%s%s payload=%" CURL_FORMAT_CURL_OFF_T
+ "/%" CURL_FORMAT_CURL_OFF_T "]",
+ msg, ws_frame_name_of_op(enc->firstbyte),
(enc->firstbyte & WSBIT_OPCODE_MASK) == WSBIT_OPCODE_CONT ?
" CONT" : "",
(enc->firstbyte & WSBIT_FIN)? "" : " NON-FIN",
@@ -839,7 +842,7 @@ static ssize_t nw_in_recv(void *reader_ctx,
CURL_EXTERN CURLcode curl_ws_recv(struct Curl_easy *data, void *buffer,
size_t buflen, size_t *nread,
- struct curl_ws_frame **metap)
+ const struct curl_ws_frame **metap)
{
struct connectdata *conn = data->conn;
struct websocket *ws;
@@ -921,7 +924,8 @@ CURL_EXTERN CURLcode curl_ws_recv(struct Curl_easy *data, void *buffer,
ctx.payload_len, ctx.bufidx);
*metap = &ws->frame;
*nread = ws->frame.len;
- /* infof(data, "curl_ws_recv(len=%zu) -> %zu bytes (frame at %zd, %zd left)",
+ /* infof(data, "curl_ws_recv(len=%zu) -> %zu bytes (frame at %"
+ CURL_FORMAT_CURL_OFF_T ", %" CURL_FORMAT_CURL_OFF_T " left)",
buflen, *nread, ws->frame.offset, ws->frame.bytesleft); */
return CURLE_OK;
}
@@ -966,10 +970,10 @@ static CURLcode ws_flush(struct Curl_easy *data, struct websocket *ws,
return CURLE_OK;
}
-CURL_EXTERN CURLcode curl_ws_send(struct Curl_easy *data, const void *buffer,
+CURL_EXTERN CURLcode curl_ws_send(CURL *data, const void *buffer,
size_t buflen, size_t *sent,
- curl_off_t totalsize,
- unsigned int sendflags)
+ curl_off_t fragsize,
+ unsigned int flags)
{
struct websocket *ws;
ssize_t nwritten, n;
@@ -987,14 +991,13 @@ CURL_EXTERN CURLcode curl_ws_send(struct Curl_easy *data, const void *buffer,
return CURLE_SEND_ERROR;
}
if(!data->conn->proto.ws) {
- failf(data, "Not a websocket transfer on connection #%ld",
- data->conn->connection_id);
+ failf(data, "Not a websocket transfer");
return CURLE_SEND_ERROR;
}
ws = data->conn->proto.ws;
if(data->set.ws_raw_mode) {
- if(totalsize || sendflags)
+ if(fragsize || flags)
return CURLE_BAD_FUNCTION_ARGUMENT;
if(!buflen)
/* nothing to do */
@@ -1027,23 +1030,24 @@ CURL_EXTERN CURLcode curl_ws_send(struct Curl_easy *data, const void *buffer,
if(space < 14)
return CURLE_AGAIN;
- if(sendflags & CURLWS_OFFSET) {
- if(totalsize) {
- /* a frame series 'totalsize' bytes big, this is the first */
- n = ws_enc_write_head(data, &ws->enc, sendflags, totalsize,
+ if(flags & CURLWS_OFFSET) {
+ if(fragsize) {
+ /* a frame series 'fragsize' bytes big, this is the first */
+ n = ws_enc_write_head(data, &ws->enc, flags, fragsize,
&ws->sendbuf, &result);
if(n < 0)
return result;
}
else {
if((curl_off_t)buflen > ws->enc.payload_remain) {
- infof(data, "WS: unaligned frame size (sending %zu instead of %zd)",
+ infof(data, "WS: unaligned frame size (sending %zu instead of %"
+ CURL_FORMAT_CURL_OFF_T ")",
buflen, ws->enc.payload_remain);
}
}
}
else if(!ws->enc.payload_remain) {
- n = ws_enc_write_head(data, &ws->enc, sendflags, (curl_off_t)buflen,
+ n = ws_enc_write_head(data, &ws->enc, flags, (curl_off_t)buflen,
&ws->sendbuf, &result);
if(n < 0)
return result;
@@ -1082,7 +1086,7 @@ CURLcode Curl_ws_disconnect(struct Curl_easy *data,
return CURLE_OK;
}
-CURL_EXTERN struct curl_ws_frame *curl_ws_meta(struct Curl_easy *data)
+CURL_EXTERN const struct curl_ws_frame *curl_ws_meta(struct Curl_easy *data)
{
/* we only return something for websocket, called from within the callback
when not using raw mode */
@@ -1096,7 +1100,7 @@ CURL_EXTERN struct curl_ws_frame *curl_ws_meta(struct Curl_easy *data)
CURL_EXTERN CURLcode curl_ws_recv(CURL *curl, void *buffer, size_t buflen,
size_t *nread,
- struct curl_ws_frame **metap)
+ const struct curl_ws_frame **metap)
{
(void)curl;
(void)buffer;
@@ -1108,19 +1112,19 @@ CURL_EXTERN CURLcode curl_ws_recv(CURL *curl, void *buffer, size_t buflen,
CURL_EXTERN CURLcode curl_ws_send(CURL *curl, const void *buffer,
size_t buflen, size_t *sent,
- curl_off_t framesize,
- unsigned int sendflags)
+ curl_off_t fragsize,
+ unsigned int flags)
{
(void)curl;
(void)buffer;
(void)buflen;
(void)sent;
- (void)framesize;
- (void)sendflags;
+ (void)fragsize;
+ (void)flags;
return CURLE_NOT_BUILT_IN;
}
-CURL_EXTERN struct curl_ws_frame *curl_ws_meta(struct Curl_easy *data)
+CURL_EXTERN const struct curl_ws_frame *curl_ws_meta(struct Curl_easy *data)
{
(void)data;
return NULL;